暗号強度のハッシュが必要ですか?必要なのが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ビット定数に置き換えてください。ああ、もう1つ。ハッシュは(ほとんどの場合と同様に)チェックされていない整数のオーバーフローに依存しています。このハッシュを「チェック済み」ブロックで実行しないでください。実行すると、例外がスローされることが事実上保証されます。