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