什么是短string(标签名称)最好的32位散列函数?
什么是相对较短的string最好的32位散列函数?
string是由英文字母,数字,空格和一些附加字符( #
, $
, .
,…)组成的标签名称。 例如: Unit testing
, C# 2.0
。
我在“最小碰撞”中寻找“最好”,performance对于我的目标并不重要。
如果性能不重要,只需采取一个安全散列(如MD5或SHA1),并将其输出截断为32位。 这会给你一个散列码的分布,这是从随机无法区分的。
我不确定这是不是最好的select,但是这是一个string的散列函数:
编程实践 (HASH表格,第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已被certificate是不错的select
乘法器在ASCIIstring的散列函数中。
对于这个迟到的回复,我感到抱歉。 今年早些时候,我撰写了一个标题为“ 散列短串 ”的页面,可能有助于此次讨论。 总之,我发现CRC-32和FNV-1a在散列短string方面更胜一筹。 他们是高效的,并在我的testing中产生广泛分布和无碰撞的哈希。 我惊讶地发现当输出被折叠为32位时,MD5,SHA-1和SHA-3产生了less量的碰撞。
你可以看看murmurhash2。 它的速度也很快,对于小弦也是如此,并且具有良好的混音最后一步,因此对于非常小的琴弦甚至是很好的混合。
如果用户添加新标签的情况很less,那么您可以使用每次添加新标签时重新计算的完美哈希( http://en.wikipedia.org/wiki/Perfect_hash_function )。 当然,如果不知道你真正想要解决的问题,那么猜测你可能会做什么。
使用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,0×46 }; #定义PRIME_MULT 1717 无符号整数 maPrime2cHash(unsigned char * str,unsigned int len) { unsigned int hash = len,i; for(i = 0; i!= len; i ++,str ++) { hash ^ = sTable [(* str + i)&255]; 散列=散列* PRIME_MULT; } 返回哈希; }
并查看www.amsoftware.narod.ru/algo2.html MaFastPrime,MaRushPrime等testing。
如果您的程序需要与其他系统通信,最好使用众所周知的algorithm。 快速和肮脏的方式是先使用md5散列的几个字符 。 您不需要花费数小时或数天的时间在您的项目中发明轮子。
缺点是有很高的碰撞几率。 但是,如果您的散列是用于时间戳会话,或短寿命任务。 使用它没有问题。
这取决于你的硬件。 在现代硬件上,即Intel / AMD,SSE4.2或arm7,应该使用内部_mm_crc32_uxx
内在函数,因为它们对于短string是最佳的。 (对于长键也是,但是最好使用Adler的线程版本,就像在zlib中一样)
在旧的或未知的硬件上,可以使用SSE4.2或CRC32function的运行时探测器,也可以使用简单的好散列函数。 如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
现在通过交stream编译器生成完美的哈希代码是如此之快,你甚至可以在飞行中创build它们,然后dynaload它。