我有一个自定义对象,我们将其称为“MyObject”,它具有三个主要属性,称为 X、Y 和 Z,用于确定它是否唯一。我有一个 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)
最佳答案
您可以轻松地从多个对象计算出合理的哈希码,如下所示:
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)));
}
对我来说看起来很快。
关于c# - 基于具有几个小数位的 double 生成唯一的哈希码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17044639/