3

可能重复:
短字符串(标签名称)的最佳 32 位哈希函数是什么?

我需要将许多字符串散列为 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)

4

3 回答 3

9

你需要一个加密强度的哈希吗?如果您只需要 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 位常量。哦,还有一件事;哈希(和大多数人一样)依赖于未经检查的整数溢出;永远不要在“已检查”块中运行此哈希,否则几乎可以保证抛出异常。

于 2012-09-04T23:23:24.437 回答
4

如果安全性不起作用,则使用加密散列函数(例如 MD5 或 SHA1)生成散列并从中获取 4 个字节是可行的。但它们比各种非加密哈希函数慢,因为这些函数主要是为安全而设计的,而不是速度。

查看非加密哈希函数,例如FNVMurmur

编辑: floodyberry.com 域现在由域停放服务注册 - 删除了死链接

于 2012-09-04T22:41:36.157 回答
3

字符串最简单但又很好的算法如下:

int Hash(string s)
{
  int res = 0; 
  for(int i = 0; i < str.Length; i++)
  {
     res += (i * str[i]) % int.MaxValue;
  }
  return res;
}

显然,这绝对不是一个安全的哈希算法,但它很快(非常快)返回 32 位,并且据我所知,它是统一的(我已经尝试过许多算法挑战,结果很好)。

不用于散列密码或任何敏感数据。

于 2012-09-04T23:14:21.003 回答