| Author |
About NaN
|
Liang Anmian
Ranch Hand
Joined: Jun 25, 2004
Posts: 119
|
|
|
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)
|
 |
Barry Gaunt
Ranch Hand
Joined: Aug 03, 2002
Posts: 7729
|
|
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 ]
|
Ask a Meaningful Question and HowToAskQuestionsOnJavaRanch
Getting someone to think and try something out is much more useful than just telling them the answer.
|
 |
Liang Anmian
Ranch Hand
Joined: Jun 25, 2004
Posts: 119
|
|
|
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
|
|
|
To find out why, I reckon you will have to read the IEEE 754 specification, Java is trying to be conformant to that.
|
 |
Andris Jekabsons
Ranch Hand
Joined: Jan 20, 2004
Posts: 82
|
|
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?
|
 |
Edwin Dalorzo
Ranch Hand
Joined: Dec 31, 2004
Posts: 961
|
|
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.
|
 |
Mike Gershman
Ranch Hand
Joined: Mar 13, 2004
Posts: 1272
|
|
The plot thickens. From the JLS:
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
|
|
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.
|
 |
Sim Kim
Ranch Hand
Joined: Aug 06, 2004
Posts: 268
|
|
Has anybody tried this : System.out.println(((new Double(Double.NaN)).equals(new Double(Double.NaN)))); Ans: True
|
 |
Mike Gershman
Ranch Hand
Joined: Mar 13, 2004
Posts: 1272
|
|
Has anybody tried this : System.out.println(((new Double(Double.NaN)).equals(new Double(Double.NaN)))); Ans: True
This is the source code of Double.equals(): Double.doubleToLongBits() collapses all possible bit representations of NaN to the canonical value, 0x7ff8000000000000L. I hope that this degree of detail will not be on the SCJP exam! [ January 16, 2005: Message edited by: Mike Gershman ] [ January 16, 2005: Message edited by: Mike Gershman ]
|
 |
 |
|
|
subject: About NaN
|
|
|