Difficulty of compareTo on floats/doubles

Joe Darcy joe.darcy at oracle.com
Thu Jul 31 20:29:10 UTC 2014


On 07/31/2014 12:43 PM, Alex M wrote:
> Hi, this is my first time posting to any OpenJDK list, so if I'm doing
> something inappropriately let me know. :)
> I saw it being suggested that "any" could perhaps support .equals() and
> .compareTo(). equals() seems to make sense -- using "==" would compare
> identity on Objects and bits on primitives, while .equals() would become ==
> for primitives and make the call on Objects. I'm not sure how plausibly the
> compareTo() idea will happen (given that would not make sense on Objects
> that don't implement Comparable, or on booleans), but one more potential
> problem with it is that floats/doubles have an undefined return value when
> comparing NaN's; they're neither less than, equal, not greater than any
> others.

While it may be surprising, the behavior is question is *not* undefined. 
The true / false behavior of ==, >, >=, <=, !=, is perfectly well 
defined by the IEEE 754 floating-point standard, behavior which is also 
found in the Java Language Specification. Nan is *unordered* with 
respect to other floating-point values.

> Unfortunately, or at least confusingly, the Float and Double classes offer
> a compareTo method which defines an order on NaNs based on their int bits
> (and which allows them to be equal to one another). This is also reflected
> in their equals() methods, such that various comparisons end up different.

The IEEE 754 == operation does not define a mathematical equivalence 
relation and the IEEE 754 < operation does not define a total order 
(besides NaN, there are signed zeros). The compareTo methods in Float 
and Double do impose an order on floating-point values where all NaN 
values are in the same equivalence class.


>          Float h=Float.NaN;
>          float i=Float.NaN;
>          System.out.println(h==i);       //False
>          System.out.println(h.equals(i));//True
>          float inf=Float.POSITIVE_INFINITY;
>          System.out.println(h<inf);           //False
>          System.out.println(h.compareTo(inf));//1 ("greater")
> These situations would need to be dealt with, even in the question of just
> allowing equality comparison -- some situations, especially with an
> implicit unboxing from a Float, will cause very strange problems.
> ~6 out of 5 statisticians say that the
> number of statistics that either make
> no sense or use ridiculous timescales
> at all has dropped over 164% in the
> last 5.62474396842 years.

More information about the valhalla-dev mailing list