基于带有几个小数点的double生成唯一的Hashcode

本文关键字:唯一 Hashcode double 有几个 小数点 于带 | 更新日期: 2023-09-27 18:17:56

我有一个自定义对象,我们将其称为"MyObject"。它有三个主要属性X,Y和Z,它们决定了它是否唯一。我有一个包含400,000个"MyObject"的HashSet。我最初生成唯一哈希码的解决方案既简单又快速。

return Convert.ToInt32(X * 76 + Y * 100 + Z * 23);

但是,由此生成的整数不够唯一。对于当前的HashCode,这两点是匹配的,尽管Y稍微不同。

X: 392598.200000000190 Y: 4935367.900000000400

X: 392598.200000000190 Y: 4935367.900580000100

我试过了:

double value = (X * 101 + Y * 89 + Z * 56);
return value.GetHashCode();
  • 非常准确,有1 - 10,000条记录,只需要几秒钟就能计算出差异。然而,拥有40万张唱片,它陷入了困境。我让它运行了17个小时,仍然没有返回我的结果。
  • 转换为字符串,然后获取字符串的哈希码。很精确,但是太慢了。
  • 增加X、Y、z的乘数,生成的数量过大。我尝试使用这里使用的方法:http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

    return ((int)value ^ (int)(value >> 32));
    

但是它不允许更多的整数。我还担心,即使我增加了大小,它也可能像我的其他解决方案一样变得无用地慢。

如果匹配,我不能做额外的检查,因为400,000条记录中有390,000条可能匹配

最好的解决方案是什么?或者有没有办法让我的两个已经很精确的操作大大加快?我正在考虑从小数点后的值中删除所有零,直到它遇到非零,然后使用我的原始逻辑,即(45.0002030将成为45.2030)

基于带有几个小数点的double生成唯一的Hashcode

您可以轻松地从几个对象中计算出合理的哈希码,如下所示:

public override int GetHashCode()
{
    int hash = 17;
    hash = hash * 23 + X.GetHashCode();
    hash = hash * 23 + Y.GetHashCode();
    hash = hash * 23 + Z.GetHashCode();
    return hash;
}

你可以添加任意多的哈希码,就像你在你的类中添加必须对哈希码做出贡献的新字段一样。

这通常是一个快速操作。

还请注意,如果您有不可变类型,您可以通过在不可变类型的构造函数中计算哈希码或按需惰性计算(然后缓存结果)来加快速度。

[编辑]

你看到你的代码变慢了,你确定那不是因为你得到了很多哈希码冲突,而不是哈希码计算本身太慢了吗?

例如,如果您对每个哈希码只返回0,它将非常快,但在一段时间后添加哈希集合将非常慢。

我希望计算这样的哈希码所花费的时间与实际将项目添加到集合所花费的时间相比会相形见绌。

(第二个编辑)

double.GetHashCode()(通过Reflector获得)的实现为:

public override unsafe int GetHashCode()
{
    double num = this;
    if (num == 0.0)
    {
        return 0;
    }
    long num2 = *((long*) &num);
    return (((int) num2) ^ ((int) (num2 >> 32)));
}

在我看来相当快