• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

About NaN

 
Ranch Hand
Posts: 119
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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 ]
 
Liang Anmian
Ranch Hand
Posts: 119
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 7729
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To find out why, I reckon you will have to read the IEEE 754 specification, Java is trying to be conformant to that.
 
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Ranch Hand
Posts: 961
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.

 
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Andris Jekabsons
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Ranch Hand
Posts: 268
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Has anybody tried this :

System.out.println(((new Double(Double.NaN)).equals(new Double(Double.NaN))));

Ans: True
 
Mike Gershman
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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 ]
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic