Possible Duplicate:
What is the best 32bit hash function for short strings (tag names)?
我需要将许多字符串散列为 32 位(uint)。
我可以只使用 MD5 或 SHA1 并从中取出 4 个字节吗?或者有更好的选择吗?
不需要安全性,也不需要关心是否被破解等。
我只需要快速统一地哈希到 32 位。 MD5和SHA1要统一。
但是我可以使用更好(更快)的内置替代方案吗?如果不是,您会使用两者中的哪一个?
这里有人问哪个更好,但不是替代品,而且存在安全问题(我不关心安全问题):
How to Use SHA1 or MD5 in C#?(Which One is Better in Performance and Security for Authentication)
您需要加密强度散列吗?如果您只需要 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 位常量。哦,还有一件事;散列(和大多数人一样)依赖于未经检查的整数溢出;永远不要在“已检查”的 block 中运行此散列,否则它几乎肯定会抛出异常。