基于具有几个小数位的双打生成唯一的哈希码

时间:2013-06-11 12:53:52

标签: c# asp.net hashcode override

我有一个自定义对象,我们将其称为“MyObject”它有三个主要属性X,Y和Z,用于确定它是否唯一。我有一个HashSet,在HashSet中包含400,000个“MyObject”。我生成唯一哈希码的原始解决方案简单而快速。

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条记录,计算差异只需几秒钟。然而,有400,000条记录,它很难陷入困境。我让它运行了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)

1 个答案:

答案 0 :(得分:2)

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

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)));
}

对我来说很快。

相关问题