user4090410
user4090410

Reputation:

How to get rid of -0 in C++

I am writing a program in which there are some operations being performed on a floating point number. After I debugged the program, I came to know that for a particular test case, the value of the variable equals -2.38418579e-07. Now I have cout precision set to 2 digits after decimal. So when I print it, it prints it as -0.00.

However, I would like the output to be 0.00 instead of -0.00. I have tried various if conditions on the variable's value. However, they do not help. Can anyone suggest how to get rid of -0.00 in C++

Upvotes: 6

Views: 985

Answers (3)

aka.nice
aka.nice

Reputation: 9382

The problem is that every floating point in a certain interval [ low , -0.0] will be printed "-0.00".

Thus you have to find low:

  • such that print(predecessor(low)) => "-0.01"
  • such that print(low) => "-0.00"

Then, you'll be able to write something like (nan apart...)

double filter(double x) {
    double low = ... ;
    return (x < low)
        ? x
        : ((x > 0.0)
            ? x
            : 0.0) ;
}

If you have a correctly rounded printf, and manage your arithmetic to be strictly IEEE754 conformant with appropriate compiler flags, the exact value of low is the nearest double to -1/200, greater than -1/200 (I write 1/200 rather than -0.005 because I'm speaking of the decimal value, not the double)

What we have with correctly rounded sscanf("-0.005","%lf",d): the double result is smaller than -1/200. I did check that with exact arithmetic like for example found in Pharo Smalltalk language:

[-0.005 < (-1/200) and: [-0.005 successor > (-1/200)]] assert.

Its successor is greater than -1/200 (necessarily, above check is just foolproofing).

Thus you can write (notice the <= low):

double filter(double x) {
    double low = 0.005 ;
    return (x <= low)
        ? x
        : ((x > 0.0)
            ? x
            : 0.0) ;
}

Upvotes: 0

2785528
2785528

Reputation: 5566

I would like the output to be 0.00 instead of -0.00

I like the other answers better. But in a crunch you can always use brute force ... (are you sure you can ignore the actual results?)

std::string rslt;
{
   std::stringstream ss;
   ss << variable;  // use same formatting as in your example

   size_t minusSignIndx = ss.str().find("-0.00");

   if (minusSignIndx != std::string::npos)
      rslt = " 0.00"; // found the nasty, ignore it
   else
      rslt = ss.str(); // not nasty, use it
}
//... use rslt

Upvotes: 0

Dimitrios Bouzas
Dimitrios Bouzas

Reputation: 42899

Firstly, you should define a tolerance number as threshold, where the absolute value of any floating point number bellow this threshold would be considered as zero. For example you could define this threshold as:

#define zero 1e-6

Then you could use the following construct to "filter" your floating point numbers:

template<typename T>
std::enable_if_t<std::is_floating_point<T>::value, T> sanitize(T &&num) {
  return std::abs(num) < zero? T{} : num;    
}

Live Demo

Notice that I use SFINAE in order for the sanitize function to accepts as input only floating point numbers.

Upvotes: 2

Related Questions