How are NaN and Infinity of a float or double stored in memory?

roblovelock picture roblovelock · Mar 22, 2016 · Viewed 8.5k times · Source

As I understand it java will store a float in memory as a 32 bit integer with the following properties:

  • The first bit is used to determine the sign
  • The next 8 bits represent the exponent
  • The final 23 bits are used to store the fraction

This leaves no spare bits for the three special cases:

  • NaN
  • Positive Infinity
  • Negative Infinity

I can guess that negative 0 could be used to store one of these.

How are these actually represented in memory?

Answer

Darshan Mehta picture Darshan Mehta · Mar 22, 2016

Java specifies that floating point numbers follow the IEEE 754 standard.

This is how it's stored:

  • bit 0 : sign bit
  • bits 1 to 11 : exponent
  • bits 12 to 63 : fraction

Now, I have executed below method with different double values:

public static void print(double d){
    System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d)));
}

I executed with these values:

print(Double.NaN);
print(Double.NEGATIVE_INFINITY);
print(Double.POSITIVE_INFINITY);
print(-Double.MAX_VALUE);
print(Double.MAX_VALUE);

And got the following output for the values above (formatted for readability):

 NaN: 0111111111111000000000000000000000000000000000000000000000000000
-Inf: 1111111111110000000000000000000000000000000000000000000000000000
+Inf: 0111111111110000000000000000000000000000000000000000000000000000
-Max: 1111111111101111111111111111111111111111111111111111111111111111
+Max: 0111111111101111111111111111111111111111111111111111111111111111

Wikipedia explains that when the exponent field is all-bits-1, the number is either Inf or NaN. Inf has all bits of the mantissa zero; NaN has at least one bit in the mantissa set to 1. The sign bit retains its normal meaning for Inf but is not meaningful for NaN. Java's Double.NaN is one particular value that will be interpreted as NaN, but there are 253−3 others.