Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何更正哈希函数?_Java_Hash_Numbers_Double - Fatal编程技术网

Java 如何更正哈希函数?

Java 如何更正哈希函数?,java,hash,numbers,double,Java,Hash,Numbers,Double,此问题是提交给at的答复的结果 我有一个名为Point的类,它基本上是“用来封装二维空间中表示的点”。我重写了hashcode()函数,如下所示: ... @Override public int hashCode() { int hash = 0; hash += (int) (Double.doubleToLongBits(this.getX()) ^ (Double.doubleToLongBits(this.getX()) >>>

此问题是提交给at的答复的结果


我有一个名为
Point
类,它基本上是“用来封装二维空间中表示的点”。我重写了
hashcode()
函数,如下所示:

...
@Override
public int hashCode() {
    int hash = 0;
    hash += (int) (Double.doubleToLongBits(this.getX())
            ^ (Double.doubleToLongBits(this.getX()) >>> 32));
    hash += (int) (Double.doubleToLongBits(this.getY())
            ^ (Double.doubleToLongBits(this.getY()) >>> 32));
    return hash;
}
...
让我澄清一下(对于那些没有检查上述链接的人),我的
点使用两个
double
s:
x
y
来表示其坐标

问题:
运行此方法时,我的问题显而易见:

public static void main(String[] args) {
    Point p1 = Point.getCartesianPoint(12, 0);
    Point p2 = Point.getCartesianPoint(0, 12);
    System.out.println(p1.hashCode());
    System.out.println(p2.hashCode());
}
我得到输出:


这显然是一个问题。基本上,我希望我的
hashcode()
为相等的点返回相等的hashcode。如果我颠倒其中一个参数声明的顺序(即,在其中一个参数声明中将
12
1
交换以获得相等的
s),我将得到正确(相同)的结果。如何在保持散列的质量或唯一性的同时纠正我的方法?

这可能是一个愚蠢的想法,因为您使用的是+这是一种对称运算,您会遇到对称问题。如果使用非对称运算,如除法(检查分母==0)或减法,该怎么办?或者你可以在文献中找到或自己发明的任何其他数字。

如果没有关于双精度中数字性质的更多信息,你无法获得两个唯一双精度的整数哈希代码

为什么?

int存储为32位表示,双精度存储为64位表示()

因此,您试图在32位空间中存储128位信息,因此它永远不会给出唯一的散列

但是

  • 这真的不是,散列码 只需要有相当罕见的碰撞就可以了
  • 如果你 了解一些关于双倍数字的知识,这会减少它们的影响 熵/信息量然后你可以用它来压缩 它们使用的位数。这将取决于申请 你还没有讨论过的这门课
  • 这就是为什么平等 通常不使用哈希代码检查是否相等, 使用每个点的getX和getY进行比较

  • 您不能使用中已经存在的代码吗

    例如,这就是番石榴在中国的用途

    如果您有Java 7,只需:

     Objects.hash(x,y)
    
    试试这个

    public int hashCode() {
        long bits = Double.doubleToLongBits(x);
        int hash = 31 + (int) (bits ^ (bits >>> 32));
        bits = Double.doubleToLongBits(y);
        hash = 31 * hash + (int) (bits ^ (bits >>> 32));
        return hash;
    }
    
    此实现遵循
    Arrays.hashCode(双a[])
    模式。 它生成以下哈希代码:

    -992476223
    1076364225
    

    您可以找到如何在有效的Java项目中编写好的哈希代码的建议。9

    在IDE中单击鼠标右键,选择“生成equals和hashCode”,然后检查IDE生成的正确实现。或者使用
    Objects.hash(x,y)
    。通常-要生成有意义的
    hashCode()
    ,每次在计算中引入另一个属性时都必须将其移动。这将导致完全相同的对称问题。他最好使用
    数组.hashCode(新的double[]{x,y})
    ,或者干脆使用
    对象.hash(x,y)
    。请注意。。。我之所以接受这个答案,是因为它是最短(也是最简单)的答案。请更详细地解释为什么使用
    31
    ?就因为31是质数?我可以改用
    23
    吗?嗯。。。有趣。似乎
    NetBeans
    也使用了这种策略:
    inthash=5;hash=41*hash+(int)(Double.doubleToLongBits(this.x)^(Double.doubleToLongBits(this.x)>>>32));hash=41*hash+(int)(Double.doubleToLongBits(this.y)^(Double.doubleToLongBits(this.y)>>>32));返回散列@ADS:请参阅有效的Java项目。9:选择值31是因为它是奇数素数…请注意,虽然这唯一地区分了这两点,但并非所有点都能保证。(见上面我的帖子)。这确实取决于计算散列的目标。
    
    public int hashCode() {
        long bits = Double.doubleToLongBits(x);
        int hash = 31 + (int) (bits ^ (bits >>> 32));
        bits = Double.doubleToLongBits(y);
        hash = 31 * hash + (int) (bits ^ (bits >>> 32));
        return hash;
    }
    
    -992476223
    1076364225