Just curious over here. How come Double.NaN is not even equal to itself? I read about this from the K & B book, and true enough, Double.NaN == Double.NaN returns false.

Current Status:<br /> <br />SCJP 1.4<br />SCJD (in progress)

I don't pretend to know much about the details, but quick glance at the Double API shows that NaN does not represent a single unique bit pattern, but a set of invalid bit patterns. It's a canonical representation for results that are not valid floating point numbers. So two NaNs may represent different things. That's my excuse for Double.NaN == Double.NaN giving the result false.

However, to confuse things even further, (new Double(Double.NaN)).equals(Double.NaN) returns true, for getting hash tables to work correctly the API says. :roll:

Oh yes, did you notice there is an isNaN() method? That's what we should be using to check if we have a NaN.

[ January 15, 2005: Message edited by: Barry Gaunt ] [ January 15, 2005: Message edited by: Barry Gaunt ]

The reason why I don't understand is that Double.NaN is a final variable in the Double wrapper class. Since it's a constant (it's value can't be changed throughout the program), how can a comparison test like this fail? It's very weird I thought.

Barry Gaunt
Ranch Hand

Joined: Aug 03, 2002
Posts: 7729

posted

0

To find out why, I reckon you will have to read the IEEE 754 specification, Java is trying to be conformant to that.

It actually kinda makes sense, because NaN is not a number, therefore regular arithmetic/boolean operations should not work with it the same way as with numbers. And if you look at the Double's source code, this is how NaN is declared: public static final double NaN = 0.0d / 0.0; So JVM must know it is not a regular number, and evaluates it accordingly. By the way, does anybody have any idea why NaN is given the value of 0x7ff8000000000000L (or 9221120237041090560L). Is it just a random number or is there some significance?

Maybe it does not help much but I took this from the IEEE754 specification:

The exceptions are C predicates � x == x � and � x != x �, which are respectively 1 and 0 for every infinite or finite number x but reverse if x is Not a Number ( NaN ); these provide the only simple unexceptional distinction between NaNs and numbers in languages that lack a word for NaN and a predicate IsNaN(x). Overoptimizing compilers that substitute 1 for x == x violate IEEE 754. IEEE 754 assigns values to all relational expressions involving NaN . In the syntax of C , the predicate x != y is True but all others, x < y , x <= y , x == y , x >= y and x > y , are False whenever x or y or both are NaN, and then all but x != y and x == y are INVALID operations too and must so signal. Ideally, expressions x !< y , x !<= y , x !>= y , x !> y and x !>=< y should be valid and quietly True if x or y or both are NaN , but arbiters of taste and fashion for ANSI Standard C have refused to recognize such expressions. In any event, !(x < y) differs from x >= y when NaN is involved, though rude compilers � optimize � the difference away. Worse, some compilers mishandle NaNs in all relational expressions.

If the argument is any value in the range 0x7ff0000000000001L through 0x7fffffffffffffffL or in the range 0xfff0000000000001L through 0xffffffffffffffffL, the result is a NaN.

So Java makes sure that NaN != NaN by using over 2^60 possible bit patterns for NaN. This way, the jvm can enforce the IEEE rule without checking for NaN during every == operation.

Mike Gershman
SCJP 1.4, SCWCD in process

Andris Jekabsons
Ranch Hand

Joined: Jan 20, 2004
Posts: 82

posted

0

Thank you both! Yesterday I was playing around a little with the NaN value and noticed that indeed NaN was represented by a range of values rather then a specific one.