20

In my code,

float f = -0.0; // Negative 

and compared with negative zero

f == -0.0f

result will be true.

But

float f = 0.0; // Positive

and compared with negative zero

f == -0.0f

also, result will be true instead of false

Why in both cases result to be true?


Here is a MCVE to test it (live on coliru):

#include <iostream>

int main()
{
    float f = -0.0;

    std::cout<<"==== > " << f <<std::endl<<std::endl;

    if(f == -0.0f)
    {
        std::cout<<"true"<<std::endl;
    }
    else
    {
        std::cout<<"false"<<std::endl;
    }
}

Output:

==== > -0  // Here print negative zero

true
YSC
  • 38,212
  • 9
  • 96
  • 149
Jayesh
  • 4,755
  • 9
  • 32
  • 62
  • 1
    `-0.0 == 0.0` is true, yet other functions differ on these two. [What operations and functions on +0.0 and -0.0 give different arithmetic results?](https://stackoverflow.com/q/25332133/2410359) – chux - Reinstate Monica Mar 04 '19 at 15:23

4 Answers4

18

C++11 introduced functions like std::signbit() which can detect signed zeros, and std::copysign() which can copy the sign bit between floating point values, if the implementation supports signed zero (e.g. due to using IEEE floating point). The specifications of those functions don't actually require that an implementation support distinct positive and negative zeros. That sort of thing aside, I'm unaware of any references in a C++ standard that even mentions signed zeros, let alone what should be the result of comparing them.

The C++ standards also do not stipulate any floating point representation - that is implementation-defined.

Although not definitive, these observations suggest that support of signed zeros, or the result of comparing them, would be determined by what floating point representation the implementation supports.

IEEE-754 is a common (albeit not the only) floating point representation used by modern implementations (i.e. compilers on their host systems). The current (published in 2008) version of IEEE-758 "IEEE Standard for Floating -Point Arithmetic" Section 5.11, second paragraph, says (bold emphasis mine)

Four mutually exclusive relations are possible: less than, equal, greater than, and unordered. The last case arises when at least one operand is NaN. Every NaN shall compare unordered with everything, including itself. Comparisons shall ignore the sign of zero (so +0 = −0). Infinite operands of the same sign shall compare equal.

Peter
  • 35,646
  • 4
  • 32
  • 74
  • 1
    Strictly speaking, IEEE754 is _sufficient_ but not _necessary_ for `std::signbit` to work. – MSalters Aug 21 '17 at 13:03
  • True, although `signbit()` was introduced along with a few other features that were clearly specified with IEEE754 in mind. Anyway, will update the answer accordingly. – Peter Aug 22 '17 at 05:39
16

Floating point arithmetic in C++ is often IEEE-754. This norm differs from the mathematical definition of the real number set.

This norm defines two different representations for the value zero: positive zero and negative zero. It is also defined that those two representations must compare equals, so by definition:

+0.0 == -0.0

As to why it is so, in its paper What Every Computer Scientist Should Know About Floating Point Arithmetic, David Goldberg, 1991-03 (linked in the IEEE-754 page on the IEEE website) writes:

In IEEE arithmetic, it is natural to define log 0 = -∞ and log x to be a NaN when x < 0. Suppose that x represents a small negative number that has underflowed to zero. Thanks to signed zero, x will be negative, so log can return a NaN. However, if there were no signed zero, the log function could not distinguish an underflowed negative number from 0, and would therefore have to return -∞.

YSC
  • 38,212
  • 9
  • 96
  • 149
  • 1
    Futher readings about IEEE-754: [IEEE Standard 754 Floating Point Numbers](http://steve.hollasch.net/cgindex/coding/ieeefloat.html) by Steve Hollasch, 2015-12-2. – YSC Aug 21 '17 at 11:11
  • 3
    The `log` argument is a bit questionable. IEEE 754-2008 recommends that both `log(+0.0)` and `log(-0.0)` should return negative infinity. (See section 9.2.1, "Special values".) – Mark Dickinson Aug 21 '17 at 17:22
13

That's because the signed negative zero must compare true with zero: i.e. -0.0 == 0.0, -0f == 0f, and -0l == 0l.

It's a requirement of any floating point scheme supported by a C++ compiler.

(Note that most platforms these days use IEEE754 floating point, and this behaviour is explicitly documented in that specification.)

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
-5

Because 0.0f and -0.0f is same negative of a zero is zero

  • 8
    If they were the same they would print the same. They are not the same. But they compare equal for `==`. – Pascal Cuoq Aug 21 '17 at 13:06
  • Q: _"Why are 0.0f and -0.0f equal?"_ ... A: _"because"_. This is a **terrible** answer: -1. – YSC Sep 08 '17 at 07:28