Proposal: Sameness operators

Joseph D. Darcy Joe.Darcy at Sun.COM
Thu May 14 22:22:16 PDT 2009


Catching up on commenting...

Reinier Zwitserloot wrote:
> The argument that .compareTo should not be used because it isn't  
> entirely congruent with either the meaning of .equals() or the  
> meanings of all the comparison operators (from == to <) on the  
> primitives, just doesn't hold water, for this simple reason:
>
> They make absolutely no sense now, either, and nobody cares about that.
>   

I care about that! ;-)

The situation is complicated, but there are reasons for the design of 
the various floating-point comparison operations.

> Here's some fun facts (all asserts are true):
>
> int x = 0/0; //ArithmeticException
> double x = 0/0.0; //okay, x = NaN
> double y = 0/0.0;
>
> assert x != y;
> assert ! (x == y);
> assert Double.valueOf(x).equals(Double.valueOf(y)); //WTF!
> assert Double.valueOf(x).equals(y); //WTF!
>
> Clearly, equals is fundamentally broken. We need a new equals! Oh no!
>   

Yes, strange but true, the "equals" relation on floating-point values 
defined by IEEE 754 is *not* an equivalence relation.  This odd 
situation arose to accommodate NaNs.  NaNs break the trichotomy of 
exactly one of the less than, equal to, or greater relations holding 
between values.  A NaN is *unordered* compared to any floating-point 
value, even itself.  Since NaNs are Not-a-Numbers they do not obey the 
rules of normal numerical values.

While the IEEE 754 design is driven by numerical programming concerns, 
at times there is a need for a true equivalence relation on 
floating-point values as well as a total ordering.  For example, 
numerical regression tests in the JDK include a boolean 
equivalent(double, double) method that returns true if both values are 
NaN or if the values are ==.  Another oddity in the IEEE 754 equals 
relation is that two distinct values, -0.0 and +0.0, are equal to each 
other.  These two values are *not* the same under IEEE 754 operations 
because 1.0/-0.0 is negative infinity while 1.0/+0.0 is positive 
infinity.  For sorting, a real total order is needed.  
Arrays.sort(double[]) uses the total ordering from Double.compareTo 
where -0.0 is less than 0.0 and NaNs are qual to one another and greater 
than positive infinity and.

[snip]


> 4. BigDecimal and BigInteger are changed to implement  
> Comparable<Number> instead. The fact that they currently don't is  
> something I don't really understand would consider filing as a bug if  
> I worked more with mixed BI/BD and primitives math. By doing this,  
> something like:
>   

Number should really have b neen an interface more clearly just meaning 
"convertible to a primitive type;" all Number lets you do is convert to 
the  primitive types and converting to primitive is not necessarily 
sufficient to let you do anything else with the value.  For example, one 
could write a Complex class that extended Number and a quaterion class 
that extended Number too.  A class like BigDecimal can't implement a 
sensible comparison on an unknown class that just happens to implement 
Number.  Even properly comparing numerical values of Number classes 
within the JDK is tricky; without specific instaneof checks, both the 
double value and long value may need to be extracted even for the 
primitive types.

-Joe



More information about the coin-dev mailing list