30

Why does this comparison give me 'false'? I looked at the source and Float.NaN is defined as

/** 
 * A constant holding a Not-a-Number (NaN) value of type
 * <code>float</code>.  It is equivalent to the value returned by
 * <code>Float.intBitsToFloat(0x7fc00000)</code>.
 */
public static final float NaN = 0.0f / 0.0f;

EDIT: surprisingly, if I do this:

System.out.println("FC " + (Float.compare(Float.NaN, Float.NaN)));

it gives me 0. So Float.compare() does think that NaN is equal to itself!

shrini1000
  • 7,038
  • 12
  • 59
  • 99

3 Answers3

69

Use Float.isNaN to check for NaN values.

pencil
  • 1,165
  • 8
  • 20
38

Because Java implements the IEEE-754 floating point standard which guarantees that any comparison against NaN will return false (except != which returns true)

That means, you can't check in your usual ways whether a floating point number is NaN, so you could either reinterpret both numbers as ints and compare them or use the much cleverer solution:

def isNan(val):
     return val != val
Voo
  • 29,040
  • 11
  • 82
  • 156
  • 6
    With the exception of `!=` comparisons, which return `true`. – Daniel Fischer Feb 18 '12 at 13:40
  • 3
    You can actually test for NaN this way! if `x==x` is false then x is NaN. – David Heffernan Feb 18 '12 at 13:41
  • 22
    You could also use the static `Float.isNaN(float)` (and Double has its version, too). – yshavit May 16 '12 at 02:50
  • I wonder what the rationale was? I understand the rationale for regarding NaN as being neither greater than, equal, nor less than anything else, but the most sensible meaning for `x==y` would be "x is indistinguishable from y", and if both x and y happen to be NaN that statement would be true. I can think of no sensible "question" which would be answered with the equality rules specified by IEEE. – supercat Aug 14 '13 at 22:02
  • @supercat I believe that the reason that !(NaN == Nan) is because NaN can be used to represent so many things. For instance, does (3.0/0.0) == (1.0/0.0)? This is tough to definitively say yes, so I think that is why they do not compare as equal. – Upgrayedd Apr 11 '14 at 17:11
  • @Upgrayedd Bad example because `3.0/0` isn't NaN but infinity (and yes that will compare equal to other infinities). Mathematically speaking it makes perfect sense: `0/0` is neither infinity nor 0, the result is indeterminate (otherwise it would violate an existing property of numbers independent what result we pick). And indeterminate results have special rules otherwise you run into paradoxes. – Voo Apr 11 '14 at 19:37
  • @Voo: It is not possible for floating-point values to obey all the axioms of arithmetic; I would posit, however, that the most important axiom for any value type, however, is that values should define equivalence classes. Even if those equivalence classes don't fully abide by all the other rules of arithmetic (e.g. x==y does not imply that 1/x == 1/y), they should at least abide by the axioms associated with equivalence classes themselves (e.g. x==y and y==z implies x==z). Were I designing a language, I would include an equality operator which would always implement an equivalence relation... – supercat Apr 12 '14 at 14:33
  • ...for any combination of operands which would compile, even if there was also a float-equality operator which implemented IEEE "equality". Mixed comparisons like `someLong==someDouble` would be allowed in only cases where the language could ensure equivalence behavior (by checking that both `(double)someLong==someDouble` and `someLong==(long)someDouble` are true). Equality operators that don't represent equivalence relations lead to muddled semantics. – supercat Apr 12 '14 at 14:38
0

All I need to say is: Wikipedia About NaN.

It is written quite clearly. The interesting part is that the floating point NaN of the common standard expresses a NaN this way:

s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx

The s is the sign (negative or positive), the 1's are the exponent and the x is regarded as a payload.

Looking at the payload a NaN is not equal any NaN and there are rare chances that these information of the payload are interesting for you as a developer (e.g. complex numbers).

Another thing is that in the standard they have signalling and quite NaN. A signalling NaN (sNaN) means an NaN that should raises a reaction like a exception. It should be used to say out loud that you have a problem in your equation. A quiet NaN (qNaN) is a NaN that is silently passed on.

A sNaN that created a signal is converted to a qNaN to not further produce any more signals in subsequent operations. Remember some system define i^0 = 1 as a constant that NaN^0 = 1 holds true. So there are cases where people calculate with NaN.

So in the end I would go with this: qNaN != sNaN but this is internal and is not observable for the user (you cant check that). Mix along the payment and the sign (yes you can have negative and positive NaN) and it appears to me that always return NaN != NaN looks like a much wiser choice that I finally learned to appreciate -> I will never ever complain or wonder about the inequality of NaN again. Praise the folks who were that thoughtful giving us such a good standard!

By the way: Java uses a positive NaN with a payload of 0 (all x are zeros).

Martin Kersten
  • 5,127
  • 8
  • 46
  • 77