[ 
https://issues.apache.org/jira/browse/NUMBERS-201?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17770479#comment-17770479
 ] 

Alex Herbert commented on NUMBERS-201:
--------------------------------------

This change introduces an incompatibility between the FP64 class and the Field 
definition for zero. The addition of zero should have no effect on the equality 
of the value before and after addition. Due to the IEEE754 result {{-0.0 + 0.0 
= 0.0}} this test fails:
{code:java}
// zero is defined such that: zero().add(a).equals(a)
FP64 a = FP64.of(-0.0);
Assertions.assertEquals(a, a.zero().add(a));
{code}
The fix would be to update the field comparison in the equals method to use:
{code:java}
public boolean equals(Object other) {
    if (other instanceof FP64) {
        final FP64 o = (FP64) other;
        return value == o.value || 
            Double.doubleToLongBits(value) == Double.doubleToLongBits(o.value);
    }
    return false;
}
{code}
This test would maintain equality for NaN values but also allow signed zeros to 
be equal. An alternative is to add zero to both values:
{code:java}
Double.doubleToLongBits(value + 0.0) == Double.doubleToLongBits(o.value + 
0.0){code}
The hashCode would have to be updated:
{code:java}
public int hashCode() {
    // Same hash code for -0.0 and 0.0
    return Double.hashCode(value + 0.0);
}
{code}

> FP64 equals is not consistent with hashCode
> -------------------------------------------
>
>                 Key: NUMBERS-201
>                 URL: https://issues.apache.org/jira/browse/NUMBERS-201
>             Project: Commons Numbers
>          Issue Type: Bug
>          Components: field
>    Affects Versions: 1.1
>            Reporter: Alex Herbert
>            Priority: Trivial
>             Fix For: 1.2
>
>
> The FP64 class wraps a {{double}} so that it can be used as a field. The 
> implementation of {{equals}} uses Precision with an allowed difference of up 
> to 2 ULP:
> {code:java}
> public boolean equals(Object other) {
>     if (other instanceof FP64) {
>         final FP64 o = (FP64) other;
>         return Precision.equals(value, o.value, 1);
>     }
>     return false;
> }{code}
> The hashCode is generated using Double.hashCode(value).
> The result is that two objects that are equal can generate a different hash 
> code. This breaks the contract of Object.equals where two objects that are 
> equal have the same hash code.
> Possible fixes:
>  # Use the equivalent of (({{{}Double)value).equals(o.value){}}} for a binary 
> equality check between values that is consistent with double.
>  # Document the class as having an equals method that is not consistent with 
> hash code. 
> I do not understand the requirement for using Precision. If a user has their 
> own tolerance for field equivalence then this should be left to them to set 
> the threshold. So I would recommend option 1.
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to