I just fixed two bugs in DrJava [1] that had to do with boxed floating-point comparisons of NaN [2] and -0.0 [3].
Both bugs had the same cause, a difference between the behavior of primitive ==
and the equals
[4] method in Double
and Float
.
According to IEEE 754, any NaN isn’t equal to anything, not even itself. Therefore, Double.NaN==Double.NaN
should evaluate to false. On the other hand, positive and negative zero are the same (even though they have different encodings), so 0.0==-0.0
should evaluate to true. This is the case for the primitive types double
and float
, but not for the boxed types Double
and Float
.
This may be surprising, but the boxed types had additional contracts to fulfill regarding the behavior of equals
and hashCode
in hash tables. It was decided that it was more important to successfully look up floating-point values in hash tables, so new Double(Double.NaN).equals(new Double(Double.NaN))
returns true, and new Double(0.0).equals(new Double(-0.0))
returns false. Try it.
In Dynamic Java, the interpreter in DrJava, we internally used boxed types when comparing primitives, just because that way, we could write the equals method more easily. Now I created special cases for floating-point numbers that unboxes the values and eschews the equals
[4] method.