哈希码 - 乘法还是异或?

问题描述 投票:0回答:1

我看到了这个哈希函数 - 它触发了一些警报:

public override int GetHashCode()
{
    var result = 0;
    unchecked {
        result = anIntId.GetHashCode();
        result *= 397 * (aString != null ? aString.GetHashCode() : 0);
    }
    return result;
}

我的自动哈希码气味修复子例程想要将其重写为:

public override int GetHashCode()
{
    var result = 0;
    unchecked {
        result = anIntId.GetHashCode() * 397;
        result = (result * 397) ^ (aString != null ? aString.GetHashCode() : 0);
    }
    return result;
}

我不记得我在哪里学到了这个模式,但似乎其中一些实际上没有意义:

  • 第一次乘以 397 看起来像是浪费时间
  • [已编辑] {在大脑减去咖啡的情况下,解释 ^ 为求幂}

这看起来正确吗,还是我犯了一些错误?

c# gethashcode
1个回答
0
投票

您引用的模式似乎是 FNV 哈希函数的变体。教科书上的定义是这样的:

algorithm fnv-1 is
    hash := FNV_offset_basis

    for each byte_of_data to be hashed do
        hash := hash × FNV_prime
        hash := hash XOR byte_of_data

    return hash

与 FNV 相比,您的第一个示例缺少 XOR 操作。您的第二个示例更接近该算法,但您认为其中一个乘法是多余的,这是正确的。因此,回答标题问题:乘法与异或(但请注意,可以使用许多其他有效的哈希函数)。

自 .NET Core 2.1 起,您可以使用

System.HashCode
来实现这些仅引用底层字段的
GetHashCode
实现:

public override int GetHashCode() => 
    HashCode.Combine(anIntId.GetHashCode(), aString.GetHashCode());

或者,更简洁,因为

anIntId
是一个整数:

public override int GetHashCode() =>
    HashCode.Combine(anIntId, aString.GetHashCode());
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.