Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion on NaN in Java

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));
System.out.println(Double.doubleToRawLongBits(nan1) == Double.doubleToRawLongBits((double)0/0));
System.out.println(Double.doubleToRawLongBits(nan3) == Double.doubleToRawLongBits(nan2));

output:

true
true
false

Please help me how the output came true for first two and false for last one. Please tell me what is actual work of Double.doubleToRawLongBits() method.

like image 203
Chandra Sekhar Avatar asked Jun 13 '12 05:06

Chandra Sekhar


People also ask

How does Java handle NaN?

In mathematics, taking the square root of a negative number results in an imaginary number. This case is dealt with by returning NaN in Java. Taking mod of a number with zero, will return the remainder after dividing a value by zero. Hence, NaN is returned.

Is NaN a double Java?

Java Double isNaN() Method The isNaN() method of Java Double class returns true: If the value of this Object is Not-a-Number (NaN). If the argument passed is Not-a-Number (NaN). Otherwise, the method returns false.

What is NaN error in Java?

In Java, "NaN" stands for "not a number" and signifies that a value is not defined. "NaN" is not an exception error, but a value that is assigned. For example, imaginary numbers like the square root of negative numbers or zero divided by zero will both print "NaN" as the result.


2 Answers

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.

like image 83
Garbage Avatar answered Sep 22 '22 23:09

Garbage


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.

like image 21
Ed Morales Avatar answered Sep 26 '22 23:09

Ed Morales