How to implement equals / hashCode methods for classes that contain double fields

I override equals and hashCode in a class that includes double fields. My first approach was to use epsilon test in the equals method and Double.hashCode (double) in hashCode, but this could lead to equal objects having different hash codes; here is a simplified example:

public class DoubleHashTest2
{
    public static void main(String[] args)
    {
        double  base1   = .9;
        double  base2   = .7;
        Test    test1   = new Test( base1 - .1 );
        Test    test2   = new Test( base2 + .1 );

        System.out.println( test1.equals( test2 ) );
        System.out.println( test1.hashCode() );
        System.out.println( test2.hashCode() );
    }

    private static class Test
    {
        private double  dnum1;

        public Test( double dnum1 )
        {
            this.dnum1 = dnum1;
        }

        public boolean equals( Test other )
        {
            final double    epsilon = .0001;
            boolean         result  = false;
            if ( this == other )
                result = true;
            else if ( other == null )
                result = false;
            else
                result  = Math.abs( this.dnum1 - other.dnum1 ) < epsilon;
            return result;
        }

        public int hashCode()
        {
            int hash    = Double.hashCode( dnum1 );
            return hash;
        }
    }
}

I thought of several solutions, including converting to BigDecimal, but I'm not very happy with any of them. Finally I decided to round:

public boolean equals( Test other )
{
    boolean         result  = false;
    if ( this == other )
        result = true;
    else if ( other == null )
        result = false;
    else
    {
        double  test1   = round( dnum1 );
        double  test2   = round( other.dnum1 );
        result  = test1 == test2;
    }
    return result;
}

public int hashCode()
{
    double  temp    = round( dnum1 );
    int hash    = Double.hashCode( temp );
    return hash;
}

private double round( double dnum )
{
    // tests for NaN and +/-infinity omitted for brevity
    final int       places      = 4;
    final double    round_const = Math.pow( 10, places );
    double result   = ((int)(dnum * round_const + .5)) / round_const;
    return result;
}

But choosing a good rounding algorithm is difficult, and it seems expensive. I looked at similar classes like Point2D.Double, but this class has no equal, for example, when comparing .8 and 0.7999999999999999.

Is there a recommended way to solve this problem?

+4
1

, Double doubleToLongBits() , Double long ( 64- ).

, equals() Double Double#compare().

equals() hashCode() :

public boolean equals(Object other) {
    if (this == other) {
        return true;
    }
    if (null == other
            || this.getClass() != other.getClass()) {
        return false;
    }

    return Double.compare(this.dnum1, ((Test) other).dnum1) == 0;
}

public int hashCode() {
    long bits = Double.doubleToLongBits(this.dnum1);
    return (int) (bits ^ (bits >>> 32));
}

Double - , . , BigDecimal?

. .

0

Source: https://habr.com/ru/post/1686583/


All Articles