Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inconsistency in java.lang.Double implementation (Oracle JDK 1.8)?

I looked at the implementation of the java.lang.Double class. The value of NaN is the specified value of 0x7ff8000000000000L. The public static final double NaN field is set to 0.0d / 0.0 which should evaluate to 0x7ff8000000000000L if the JVM does implement it that way.

  1. Why was this value (0x7ff8000000000000L) chosen? Is there anything special about that value (e.g. its bit mask)?

  2. Why is the field implicitly set to that value and depends on the underlying implementation of the 0.0d / 0.0 operation whereas the static method public static long doubleToLongBits(double value) sets the value explicitly to 0x7ff8000000000000L for a NaN argument? Wasn't it much safer to implicitly set it as the result of 0.0d / 0.0 highly depends on the implementation of the JVM and could be changed (most likely it never will) theoretically?

The same goes for POSITIVE_INFINITY and NEGATIVE_INFINITY. Fields are implicitly set to their values but some methods use the explicit specified values. Is there a reason behind that?

Thanks for helping me to learn anything new each day :-).

like image 957
Markus Steppberger Avatar asked Mar 04 '23 07:03

Markus Steppberger


1 Answers

The public static final double NaN field is set to 0.0d / 0.0 which should evaluate to 0x7ff8000000000000L if the JVM does implement it that way.

No: it results in NaN, per the language spec:

Division of a zero by a zero results in NaN

0x7ff8000000000000L is a long, not a double, hence that cannot be used as the field initializer directly.

The documentation of Double.NaN does state that its value "is equivalent to the value returned by Double.longBitsToDouble(0x7ff8000000000000L)." However, 0.0d / 0.0 is used in preference to that to initialize the field because it is a compile-time constant value, whereas method invocations are not.

(Shameless plug for my answer about why it is 0.0d, not 0.0)


Why was this value (0x7ff8000000000000L) chosen?

As noted in JLS Sec 4.2.3:

IEEE 754 allows multiple distinct NaN values for each of its single and double floating-point formats. While each hardware architecture returns a particular bit pattern for NaN when a new NaN is generated, a programmer can also create NaNs with different bit patterns to encode, for example, retrospective diagnostic information.

For the most part, the Java SE Platform treats NaN values of a given type as though collapsed into a single canonical value, and hence this specification normally refers to an arbitrary NaN as though to a canonical value.

The Double.longBitsToDouble method has to return a value, so this is the value they chose to return.

like image 163
Andy Turner Avatar answered Apr 01 '23 08:04

Andy Turner