DoubleBuffer.compareTo is not anti-symmetric
Joseph D. Darcy
Joe.Darcy at Sun.COM
Tue Nov 24 17:45:57 PST 2009
Martin Buchholz wrote:
> On Sun, Nov 22, 2009 at 07:41, Alan Bateman <Alan.Bateman at sun.com> wrote:
>
>> Martin Buchholz wrote:
>>
>>> I have a webrev for y'all at
>>>
>>> http://cr.openjdk.java.net/~martin/webrevs/openjdk7/DoubleBuffer/
>>>
>>> 6666666: (bf) Improve floating-point buffer comparison
>>>
>>> Describe the exact behavior of {Double,Float}Buffer.{equals,compareTo}.
>>>
>>> Fix the behavior of
>>> {Double,Float}Buffer.compareTo
>>> so that it satisfies the Comparable contract.
>>>
>>> I'd also like to fix the behavior of {Double,Float}Buffer.equals to be
>>> compatible with {Double,Float}.equals, but the proposed change assumes
>>> that we are stuck with the historic behavior and should simply
>>> document it.
>>>
>>> Martin
>>>
>>>
>> I've created this bug to track this:
>> 6903754: (bf) Improve floating-point buffer comparison
>>
>> I haven't had time yet to fully digest the proposal (at least, from an
>> initial glance, the 0.0/-0.0 case where it looks like equals and compareTo
>> will now be inconsistent).
>>
>
> Yes, you're right - a sad situation.
>
> I'd like to change the behavior so that e.g.
> DoubleBuffer.equals compares corresponding elements using Double.equals
> and
> DoubleBuffer.compareTo compares corresponding elements using Double.compareTo
>
> but maybe that's too bold a step for the JDK.
>
> I can also do the minimal patch to compareTo
> that considers NaN as greater than any other value.
> But that would be introducing yet another
> way of comparing floating point values.
> Hmmmmm....I'm sadly talking myself into taking that
> conservative but disagreeable decision.
> OK. Done.
>
> One passing comment on the javadoc update is that
>
>> the clarification as to how equals behaves might be better to be part of
>> item 3 rather than starting a new item (as it logically follows).
>>
>
> ?! It does not start a new <li> - just a new <p>
>
>
>> Also given
>> that these are buffers of primitive types then an alternative would be to be
>> explicit as to how it it differs from the Java Language == operator and do a
>> "see also" for Double#equals(double)? Minor comment on compareTo is that
>> "invoking" would be more consistent than "using".
>>
For the morbidly curious, I thought I would send in a few comments on
the nature of IEEE 754 floating-point equality.
First, the IEEE 754 standard defines four mutually exclusive possible
ordering relations between numbers:
* equal
* greater than
* less than
* unordered
A NaN is unordered with respective to every floating-point value,
including itself. This was done so that NaNs would not quietly slip by
without due notice. Since (NaN == NaN) is false, the IEEE 754 "=="
relation is *not* an equivalence relation. There are other ways IEEE
754 == is not an equivalence relation. For example, the two values -0.0
and +0.0 compare as equal, but they are not equivalent since 1.0/-0.0 =>
-infinity and 1.0/+0.0 => + infinity. There are two zeros in IEEE 754
because there are two infinities. Another way to add infinity to the
real numbers is to have a single (unsigned) projective infinity. In
such a system, there is only one zero. Early x87 chips before IEEE 754
was standardized had support for both signed (affine) and projective
infinities. The different ways of adding infinity are more convenient
for different kinds of computations.
However, there are cases where one wants an true equivalence relation
over floating-point values, such as test programs, and one needs a total
ordering, such as when sorting. In my numerical tests I have methods
that return true if:
(x == y) && (if x and y are both zero they have the same sign) || (x and
y are both NaN)
which is conveniently computed using (Double.compareTo(x, y) == 0). For
sorting or a total order, the semantics of Double.compareTo are fine; it
doesn't matter where the NaNs are ordered to as long as they are
consistently ordered.
I wasn't aware of a mixture of IEEE 754 and Double.compareTo being used
in the Buffer classes, but I'm not confident I can asses the behavioral
compatibility impact of switching the implementation algorithm.
-Joe
More information about the nio-dev
mailing list