commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Phil Steitz <phil.ste...@gmail.com>
Subject Re: [math] Issue with equals/hashCode on Complex/Dfp instances
Date Tue, 15 Apr 2014 16:52:08 GMT
On 4/15/14, 5:19 AM, Gilles wrote:
> On Tue, 15 Apr 2014 08:03:51 +0900, Cyrille Artho wrote:
>> Dear all,
>> Java's default contract (in Object) states that two objects with
>> equal data should return the same hashCode. In other words, if
>> a.equals(b), their return value of hashCode() must be the same.
>>
>> Unfortunately, with Double values, new Double(0.0d).equals(new
>> Double(-0.0d)) is false. This is because their internal
>> representation
>> differs. Java's built-in Double thus returns a different hashCode
>> for
>> 0.0d and -0.0d.
>>
>> However, Apache's math library uses a mathematical comparison for
>> Complex/Dfp (perhaps also others), where 0.0d == -0.0d. This breaks
>> the contract, and thus causes problems when Complex or Dfp instances
>> are used in containers such as HashMap, HashSet, etc. See the bug
>> report for more details and test cases:
>>
>> https://issues.apache.org/jira/browse/MATH-1118
>>
>> It is not quite clear how this should be fixed. Gilles posted a
>> patch
>> that uses Java's equals to perform the comparison. This fixes the
>> behavior w.r.t. the contract but may surprise people who expect a
>> mathematical comparison.
>>
>> Another possible fix (without a tentative patch at this time) would
>> be to change hashCode:
>>
>>     public int hashCode() {
>>         if (imaginary == 0.0d && real == 0.0d) {
>>             return ZERO.hashCode();
>>         }
>>     ...
>>
>> and similar for Dfp.
>>
>> This fixes the issue for zero values. However, there may be issues
>> with normalized vs. unnormalized floating point values with the same
>> (mathematical) value but different internal representations, where
>> this kind of fix cannot be used. I'm not familiar enough with
>> various
>> floating point implementations to know if Java always normalizes the
>> values before using them in a statement like hashCode().
>>
>> Therefore, the suggestion above is mathematically nice for +/- 0.0d,
>> but otherwise much less safe than Gilles' patch.
>>
>> Any comments? Probably best post them on JIRA:
>>
>> https://issues.apache.org/jira/browse/MATH-1118
>
> IIUC, fixing the "hashCode" method as above would not solve the
> problem
> since it deals only with "0" whereas the unit test fails for "-i".

Thanks.  I get that now.
>
> Do we agree that we first have to decide whether "Complex" should
> behave
> as "Double"?
>
> If the answer is "no" (as is the case now), shouldn't we document
> that
> "hash tables will not operate properly" (cf. Javadoc for "Double")?
> And is this behaviour acceptable?

I don't think having equal instances hashing to different values is
acceptable.  We have to do something to fix that.
>
> One possibility is to have the "equals(Complex)" behave according to
> the JDK semantics, and add a static method "equals(Complex, Complex)"
> that would implement mathematical comparison (where "-0" == "0").

I like the idea of imitating the way Double works for equals.

Phil
>
>
> Regards,
> Gilles
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Mime
View raw message