你需要一个加密强度的哈希吗?如果您只需要 32 位,我敢打赌。
试试 Fowler-Noll-Vo 哈希。它速度快,具有良好的分布和雪崩效应,通常可以用于哈希表、校验和等:
public static uint To32BitFnv1aHash(this string toHash,
bool separateUpperByte = false)
{
IEnumerable<byte> bytesToHash;
if (separateUpperByte)
bytesToHash = toHash.ToCharArray()
.Select(c => new[] { (byte)((c - (byte)c) >> 8), (byte)c })
.SelectMany(c => c);
else
bytesToHash = toHash.ToCharArray()
.Select(Convert.ToByte);
//this is the actual hash function; very simple
uint hash = FnvConstants.FnvOffset32;
foreach (var chunk in bytesToHash)
{
hash ^= chunk;
hash *= FnvConstants.FnvPrime32;
}
return hash;
}
public static class FnvConstants
{
public static readonly uint FnvPrime32 = 16777619;
public static readonly ulong FnvPrime64 = 1099511628211;
public static readonly uint FnvOffset32 = 2166136261;
public static readonly ulong FnvOffset64 = 14695981039346656037;
}
这对于基于每个对象的字符串摘要(自定义 ToString() 或其他)为 GetHashCode 创建语义上等价的哈希非常有用。您可以重载它以IEnumerable<byte>
使其适合校验和流数据等。如果您需要 64 位哈希 (ulong),只需复制函数并将使用的常量替换为 64 位常量。哦,还有一件事;哈希(和大多数人一样)依赖于未经检查的整数溢出;永远不要在“已检查”块中运行此哈希,否则几乎可以保证抛出异常。