int i = 0, j = 0;
double nan1 = (double)0/0;
double nan2 = (double)0/0;
double nan3 = (double)i/j;
System.out.println(Double.doubleToRawLongBits(nan1) == Double.doub
Please try to run following code to see the values:
public class Test
{
public static void main(String[] args){
int i = 0, j = 0;
double nan1 = (double)0/0;
double nan2 = (double)0/0;
double nan3 = (double)i/j;
System.out.println(Double.doubleToRawLongBits(nan1) + " == "+ Double.doubleToRawLongBits(nan2) + " is " +
(Double.doubleToRawLongBits(nan1) == Double.doubleToRawLongBits(nan2)));
System.out.println(Double.doubleToRawLongBits(nan1) + " == "+ Double.doubleToRawLongBits((double)0/0) + " is " +
(Double.doubleToRawLongBits(nan1) == Double.doubleToRawLongBits((double)0/0)));
System.out.println(Double.doubleToRawLongBits(nan3) + " == "+ Double.doubleToRawLongBits(nan2) + " is " +
(Double.doubleToRawLongBits(nan3) == Double.doubleToRawLongBits(nan2)));
}
}
On my Mac, it produces following output:
9221120237041090560 == 9221120237041090560 is true
9221120237041090560 == 9221120237041090560 is true
-2251799813685248 == 9221120237041090560 is false
This pitfall is documented in the Javadoc for the doubleToRawLongBits method:
If the argument is NaN, the result is the long integer representing the actual NaN value. Unlike the doubleToLongBits method, doubleToRawLongBits does not collapse all the bit patterns encoding a NaN to a single "canonical" NaN value.
The IEEE 754 standard allows different bit patterns for NaN
. For computation and comparison purposes they should all work the same (i.e. NaN
compares not equal to itself, is not ordered and every computation involving NaN
is NaN
itself). With doubleToRawLongBits
you get the exact bit pattern used. This is also detailed in the JLS:
For the most part, the Java platform treats NaN values of a given type as though collapsed into a single canonical value (and hence this specification nor- mally refers to an arbitrary NaN as though to a canonical value). However, version 1.3 the Java platform introduced methods enabling the programmer to distinguish between NaN values: the
Float.floatToRawIntBits
andDouble.double- ToRawLongBits
methods. The interested reader is referred to the specifications for theFloat
andDouble
classes for more information.
In your case the sign bit is different, in this case I can direct you to Wikipedia, which summarises this concisely:
In IEEE 754 standard-conforming floating point storage formats, NaNs are identified by specific, pre-defined bit patterns unique to NaNs. The sign bit does not matter.
Both your values are NaN
, they just use different bits to represent that. Something that is allows by IEEE 754 and in this case probably stems from the compiler substituting Double.NaN
for a constant computation that results in NaN
while the actual hardware gives a different result, as suspected by Mysticial in a comment to the question already.
The reason is because when you divide a double variable 0 by 0 it returns NaN, so the method doesnt have a single canonical representation in binary, so it may return the binary of NaN as 7F F8 00 00 00 00 00 00 or FF F8 00 00 00 00 00 00.
Even though technically they represent the same thing, which is NaN, its different in binary representation.
I think Java follows IEEE 754. In this case NaN has more than one possible bit representation. The two representations in your case differ in the "sign" bit. The value of the sign bit seems to be not defined by the standard and is usually ignored. So both values are correct. See http://en.wikipedia.org/wiki/NaN