c# - Double.GetHashCode() 的 C# 缺陷
问题描述
双打的位格式将符号存储在第一位。双精度的 C# 哈希算法是高 32 位和低 32 位的二进制异或。
因此,当您散列双 A 及其负数 -A 时,散列的唯一区别在于第一位。
要散列多个字段,大多数参考建议使用如下内容:
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + field1.GetHashCode();
hash = hash * 23 + field2.GetHashCode();
return hash;
}
}
最后,考虑两个对象,每个对象都有两个双精度对象,如下所示:
对象 1:{A,-B} 对象 2:{-A,B}
对于任何两个双精度数 A 和 B,这两个对象似乎总是哈希到相同的值(使用上面的方法,无论种子和乘数如何)。大致原理是,熵存储在最高有效位中,并且该位溢出丢失重要信息。
我希望对具有相似性能但熵更高的双打使用不同的哈希。有什么建议么?
编辑:请不要写/评论碰撞的必然性。
解决方案
你可以散列long
。替换int hash
为long hash
,例如:
public override int GetHashCode()
{
unchecked
{
long hash = 17;
hash = hash * 23 + field1.GetHashCode();
hash = hash * 23 + field2.GetHashCode();
return hash.GetHashCode();
}
}
现在您消除了溢出问题。从我所做的测试中(在一对夫妇double
:-) )你的问题。
推荐阅读
- python - 使用列表中的索引来获取另一个列表中的另一个值/元素
- amazon-web-services - 如何将不可用的包添加到 EC2 实例?
- javascript - 如何实现 Next.js SVG 加载器
- statistics - 如果我们知道消息,我们可以猜测 HMAC-SHA256 哈希的前 2 个字符,可以看到所有结果但不知道密钥吗?
- reactjs - 如何使用 react-draggable 将拖动的组件重置为其原始位置?
- amazon-web-services - 使用 bash 脚本在 Cognito 中查找并确认未确认的用户
- xslt - 如何使用 XSLT 转换按标签分隔值/循环标签
- python - 如何解决错误:不支持的格式或损坏的文件:预期的 BOF 记录;找到 b'