对于相对较短的字符串,最好的32位散列函数是什么?
字符串是由英文字母,数字,空格和一些其他字符组成的标记名称(#
,$
,.
,...)。例如:Unit testing
,C# 2.0
。
我在“最小碰撞”中寻找'最佳',表现对我的目标并不重要。
答案 0 :(得分:23)
我不确定它是否是最佳选择,但这里是字符串的哈希函数:
The Practice of Programming(HASH TABLES,第57页)
/* hash: compute hash value of string */
unsigned int hash(char *str)
{
unsigned int h;
unsigned char *p;
h = 0;
for (p = (unsigned char*)str; *p != '\0'; p++)
h = MULTIPLIER * h + *p;
return h; // or, h % ARRAY_SIZE;
}
经验,值31和37具有 被证明是很好的选择 ASCII字符串的哈希函数中的乘数。
答案 1 :(得分:22)
如果性能不重要,只需采用安全散列(如MD5或SHA1),并将其输出截断为32位。这将为您提供与随机无法区分的哈希码分布。
答案 2 :(得分:14)
对不起,我很抱歉。今年早些时候,我编写了一个标题为Hashing Short Strings的页面,这可能对本次讨论有所帮助。总之,我发现CRC-32和FNV-1a优于散列短串。在我的测试中,它们是高效的并且产生广泛分布和无碰撞的哈希。当输出折叠下降到32位时,我惊讶地发现MD5,SHA-1和SHA-3产生了少量冲突。
答案 3 :(得分:1)
你可以查看murmurhash2。它速度快,也适用于小弦乐,并且具有良好的混合最终步骤,因此即使是非常小的琴弦也能很好地混合。
答案 4 :(得分:1)
这取决于你的硬件。
在现代硬件上,即具有SSE4.2或arm7的Intel / AMD,您应该使用内部_mm_crc32_uxx
内在函数,因为它们是短字符串的最佳选择。 (对于长按键,但最好使用Adler的线程版本,如zlib)
在旧的或未知的硬件上,可以是SSE4.2或CRC32功能的运行时探测,也可以只使用简单好的哈希函数。例如。 Murmur2或城市
质量和性能概述如下: https://github.com/rurban/smhasher#smhasher
还有所有实现。最喜欢的是https://github.com/rurban/smhasher/blob/master/crc32_hw.c和https://github.com/rurban/smhasher/blob/master/MurmurHash2.cpp
如果您事先知道密钥,请使用完美哈希,而不是哈希函数。例如。 gperf 或 phash :https://github.com/rurban/Perfect-Hash#name
如今通过c编译器生成完美的哈希是如此之快,你甚至可以动态创建它们,并且可以将它们dynaload。
答案 5 :(得分:0)
如果用户很少添加新标签,那么您可以使用每次添加新标签时重新计算的完美哈希值(http://en.wikipedia.org/wiki/Perfect_hash_function)。当然,在不知道你真正试图解决的问题的情况下,猜测你可能会做些什么是猜测。
答案 6 :(得分:0)
使用MaPrime2c哈希函数:
static const unsigned char sTable[256] = { 0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9, 0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28, 0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53, 0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2, 0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8, 0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90, 0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76, 0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d, 0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18, 0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4, 0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40, 0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5, 0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2, 0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8, 0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac, 0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46 }; #define PRIME_MULT 1717 unsigned int maPrime2cHash (unsigned char *str, unsigned int len) { unsigned int hash = len, i; for (i = 0; i != len; i++, str++) { hash ^= sTable[( *str + i) & 255]; hash = hash * PRIME_MULT; } return hash; }
并查看www.amsoftware.narod.ru/algo2.html以获取MaFastPrime,MaRushPrime等测试。
答案 7 :(得分:0)
如果您的程序需要与其他系统通信,最好使用众所周知的算法。快速&脏的方法是首先使用md5哈希的几个字符。您不需要花费数小时或数天来发明项目中的轮子。
缺点是碰撞机率很高。但是,如果您的哈希是用于带时间戳的会话,或者是短期生命周期任务。使用它没有问题。