Search code examples
cieee-754comparison-operators

Cases where float == and != are not direct opposites


In https://github.com/numpy/numpy/issues/6428, the root cause for the bug seems to be that at simd.inc.src:543, a compiler optimizes !(tmp == 0.) to tmp != 0..

A comment says that these are "not quite the same thing." But doesn't specify any details. NaNs are mentioned further on, but a test shows that a NaN compares to 0. the expected way.

What are the cases where == and != can both return true/false?

Or the discrepancy is in another field - e.g. returning values that have the same truth value but are different as ints (but testing shows even this doesn't seem the case)?


Solution

  • A comment says that these are "not quite the same thing." But doesn't specify any details. NaNs are mentioned further on, but a test shows that a NaN compares to 0. the expected way.

    What are the cases where == and != can both return true/false?

    The standard says:

    The == (equal to) and != (not equal to) operators are analogous to the relational operators except for their lower precedence. [...] For any pair of operands, exactly one of the relations is true.

    (C2011, 6.5.9/3; emphasis added)

    Therefore, for any expressions X and Y that are jointly allowed as operands of these operators, (X) != (Y) must evaluate to the same result as !((X) == (Y)). If they are found in practice not to do so, then the compiler that yielded that result is non-conforming in that respect. If that non-conformance is unexpected, then it constitutes a bug in the compiler.

    Additionally, I observe that 6.5.9/3 applies just as much to NaNs, infinities, and subnormals as to any other operands. NaNs are special with respect to these operators for a different reason: NaNs compare unequal to all operands, including themselves (supposing IEEE semantics).