首页 > 解决方案 > 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,这两个对象似乎总是哈希到相同的值(使用上面的方法,无论种子和乘数如何)。大致原理是,熵存储在最高有效位中,并且该位溢出丢失重要信息。

我希望对具有相似性能但熵更高的双打使用不同的哈希。有什么建议么?

编辑:请不要写/评论碰撞的必然性。

标签: c#hashdouble

解决方案


你可以散列long。替换int hashlong hash,例如:

public override int GetHashCode()
{
    unchecked
    {
        long hash = 17;

        hash = hash * 23 + field1.GetHashCode();
        hash = hash * 23 + field2.GetHashCode();

        return hash.GetHashCode();
    }
}

现在您消除了溢出问题。从我所做的测试中(在一对夫妇double:-) )你的问题。


推荐阅读