如何为精度有限的双精度值编写适当的哈希码方法? [英] How to write a proper hashcode method for double values with limited precision?

查看:180
本文介绍了如何为精度有限的双精度值编写适当的哈希码方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果double成员在另一个对象的给定范围内,则认为类Foo的对象相等.由于浮点运算,很容易引入这种错误.

An object of class Foo is considered equal if the double members are within a given range of the other object. Such an error can easily be introduced due to floating point arithmetic.

方法isDoubleEqualsdoubleArrayEquals将处理equals部分,但合同规定,对于相等的对象,哈希码必须相同. 默认的double哈希码不会将close值映射到相同的值,因此,对于匹配double而言,获得相同哈希值的一种好方法是什么?

The method isDoubleEquals and doubleArrayEquals will take care of the equals part but the contract states that the hashcode has to be identical for equal objects. The default hashcode of doubles will not map close values to the same value, therefore what would be a good approach to get the same hash value for matching doubles?

public class Foo {

    double[] values;

    public Foo(double[] values) {
        this.values = values;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        //TODO Arrays.hashCode will not work with the contract
        result = prime * result + Arrays.hashCode(values);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Foo other = (Foo) obj;
        if (!doubleArrayEquals(values, other.values,1e-10))
            return false;
        return true;
    }

    private boolean doubleArrayEquals(double[] arr, double[] arr2, double epsilon) {
        if (arr== arr2)
            return true;
        if (arr == null || arr2 == null)
            return false;

        int length = arr.length;
        if (arr2.length != length)
            return false;

        for(int i = 0; i < length; i++) {
            if(!isDoubleEquals(arr[i],arr2[i],epsilon)) {
                return false;
            }
        }
        return true;
    }

    private boolean isDoubleEquals(double needle, double target, double epsilon) {
        return Math.abs(needle - target) <= epsilon;
    }
}

推荐答案

不能正确编写处理近似相等的equalshashCode方法.

You cannot properly write equals and hashCode methods which deal with approximate equality.

equals的合同需要可传递性,而近似相等性不是可传递性.

The contract of equals requires transitivity, and approximate equality is not transitive.

并不是说近似相等不是一件有用的事情:这不是Java的equals(和hashCode)方法的用途,因此您应该定义自己的方法-例如isApproximatelyEqualTo-支持它,而不会重载众所周知的Java方法.

That's not to say that approximate equality is not a useful thing: it's just not what Java's equals (and hashCode) methods are for, and therefore you should define your own method - say, isApproximatelyEqualTo - to support it, without overloading the well-known Java methods.

这篇关于如何为精度有限的双精度值编写适当的哈希码方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆