12

As in this question is said, there is some differences between negative and positive zero in floating point numbers. I know it's because of some important reasons. what I want to know is a short code to avoid negative zero in output.

for example in the following code:

cout << fixed << setprecision(3);
cout << (-0.0001) << endl;

"-0.000" is printed. but I want "0.000".

Note all other negative numbers (e.g. -0.001) should still be printed with the minus sign preceding them, so simply * -1 will not work.

Tas
  • 7,023
  • 3
  • 36
  • 51
Ali
  • 6,808
  • 3
  • 37
  • 47
  • @TonyTheLion what if my number is -0.001? it sould be printed -0.001 and I shouldn't * -1 this. – Ali Sep 21 '12 at 18:45
  • AFAIK a minus number multiplied by another minus number yields a positive number. That's basic maths. What's your point? – Tony The Lion Sep 21 '12 at 18:47
  • You will have to check that your number is not positive before you do the *-1, else you'll get a negative number as output. – Tony The Lion Sep 21 '12 at 18:48
  • 1
    @TonyTheLion I should multiply by -1 only when the result is -0.000. not all negative numbers as you said "You will have to check that your number is not positive before you do the *-1" – Ali Sep 21 '12 at 18:51
  • You seem to be talking about two separate things: negative zero, and a negative number small enough that it rounds to zero when printed so some particular precision. Which do you want to prevent? – Jerry Coffin Sep 21 '12 at 19:03

3 Answers3

4

Try depending on your precision.

cout << ((abs(ans) < 0.0005)? 0.000: ans) << endl;

Mahmoud Aladdin
  • 536
  • 1
  • 3
  • 13
  • it should be: 'cout << (abs(ans) < 0.0005)? 0.000: ans << endl;' – Ali Sep 21 '12 at 18:56
  • 1
    @wallyk: You can't return different types from a conditional expression in C++. – nneonneo Sep 21 '12 at 19:00
  • @wallyk it's not needed. becuase setprecision(3) is called before that. – Ali Sep 21 '12 at 19:00
  • @nneonneo: Oh, yeah. I have been doing too much javascript and php lately. – wallyk Sep 21 '12 at 19:02
  • This code does not compile. `<<` has higher precedence than `?:`, so it is parsed with `ans << endl` as a subexpression. This fails to resolve because `ans` is presumably a floating-point type, and no insert operator (`<<`) is declared for it with the type of `endl`. – Eric Postpischil Sep 21 '12 at 19:14
  • Add parenthisis around the ()?: combination, it should work fine!! – Mahmoud Aladdin Sep 21 '12 at 19:21
  • @Eric: it should be parsed as (cout.operator<<(()?:)).operator<<(endl); Why does it behave the way you say it does?! – Mahmoud Aladdin Sep 21 '12 at 19:29
  • 1
    @Aladdin: `<<` has higher precedence than `?:`. In the C++ formal grammar, `<<` is parsed with `shift-expression → shift-expression << additive-expression`, and `?:` is parsed with `conditional-expression → logical-or-expression ? expression : assignment-expression`. Because of other rules of the grammar, `ans << endl` can be an `assignment-expression`, but an unparenthesized `…?…:…` cannot be a `shift-expression`. Therefore, the `<<` rule must be used to reduce `ans << endl` before the `?:` expression can be reduced. – Eric Postpischil Sep 21 '12 at 19:58
3

How about:

cout << (value == 0.0 ? abs(value) : value)  << endl;
GreyBeardedGeek
  • 29,460
  • 2
  • 47
  • 67
  • 2
    There are plenty of resources online explaining why `value == 0.0` is a bad idea. http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html is good – IronMensan Sep 21 '12 at 20:14
  • This answer would be correct (and a good idea) if the questioner really only wanted to catch negative 0. But the body of the question shows that's not the case. – Steve Jessop Sep 21 '12 at 21:36
  • @IronMensan - what a got from that article was that "the IEEE standard defines comparison so that +0 = -0"...so I'm genuinely interested - can you point me to something that more explicitly explains the problem? Steve Jessop - it looks to me like the body of the question asked specifically about negative 0 only. Did I miss something? – GreyBeardedGeek Sep 22 '12 at 01:07
  • 1
    Yes, the body of the question says that the questioner wants `"0.000"` to be printed instead of `"-0.000"` for the value `-0.0001`. So it's not just negative zero that needs to be treated specially, `-0.0001` does too. Basically, the questioner is referring to any output of `"-0.000"` from `cout` as "negative zero", they don't just mean an IEEE negative zero in `value`. – Steve Jessop Sep 24 '12 at 08:50
1

If you care about arbitrary precision, as opposed to just a fixed one at 3, you'll need a small bit of work. Basically, you'll have to do a pre-check before the cout to see if the number will get formatted in a way you don't like.

You need to find the order of magnitude of the number to see if it the imprecise digits will be lost, leaving only the sign bit.

You can do this using the base 10 logarithm of the absolute value of the number. If negative of result is greater than the precision you have set, the number will show in a way you don't want.

log10 of 0.0001 is -4.

negative of (-4) is 4.

4 > 3 (the arbitrary precision) Thus the value will show up unhappily.

In very bad pseudocode:

float iHateNegativeZeros(float theFloat, int precision)
{
   if((theFloat < 0.0f) &&
      (-log10(abs(theFloat)) > precision))
   {
     return -theFloat;
   }
   else
   {  
     return theFloat;
   }
}
Ross
  • 1,313
  • 4
  • 16
  • 24