关闭

DJBX33A (Daniel J. Bernstein, Times 33 with Addition) APR哈希默认算法

314人阅读 评论(0) 收藏 举报

经典是经过了时间考验的

  1. APR_DECLARE_NONSTD(unsigned  int ) apr_hashfunc_default( const   char  *char_key,  
  2.                                                       apr_ssize_t *klen)  
  3. {  
  4.     unsigned int  hash = 0;  
  5.     const  unsigned  char  *key = ( const  unsigned  char  *)char_key;  
  6.     const  unsigned  char  *p;  
  7.     apr_ssize_t i;  
  8.       
  9.     /*  
  10.      * This is the popular `times 33' hash algorithm which is used by  
  11.      * perl and also appears in Berkeley DB. This is one of the best  
  12.      * known hash functions for strings because it is both computed  
  13.      * very fast and distributes very well.  
  14.      *  
  15.      * The originator may be Dan Bernstein but the code in Berkeley DB  
  16.      * cites Chris Torek as the source. The best citation I have found  
  17.      * is "Chris Torek, Hash function for text in C, Usenet message  
  18.      * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich  
  19.      * Salz's USENIX 1992 paper about INN which can be found at  
  20.      * <http://citeseer.nj.nec.com/salz92internetnews.html>.  
  21.      *  
  22.      * The magic of number 33, i.e. why it works better than many other  
  23.      * constants, prime or not, has never been adequately explained by  
  24.      * anyone. So I try an explanation: if one experimentally tests all  
  25.      * multipliers between 1 and 256 (as I did while writing a low-level  
  26.      * data structure library some time ago) one detects that even  
  27.      * numbers are not useable at all. The remaining 128 odd numbers  
  28.      * (except for the number 1) work more or less all equally well.  
  29.      * They all distribute in an acceptable way and this way fill a hash  
  30.      * table with an average percent of approx. 86%.  
  31.      *  
  32.      * If one compares the chi^2 values of the variants (see  
  33.      * Bob Jenkins ``Hashing Frequently Asked Questions'' at  
  34.      * http://burtleburtle.net/bob/hash/hashfaq.html for a description  
  35.      * of chi^2), the number 33 not even has the best value. But the  
  36.      * number 33 and a few other equally good numbers like 17, 31, 63,  
  37.      * 127 and 129 have nevertheless a great advantage to the remaining  
  38.      * numbers in the large set of possible multipliers: their multiply  
  39.      * operation can be replaced by a faster operation based on just one  
  40.      * shift plus either a single addition or subtraction operation. And  
  41.      * because a hash function has to both distribute good _and_ has to  
  42.      * be very fast to compute, those few numbers should be preferred.  
  43.      *  
  44.      *                  -- Ralf S. Engelschall <rse@engelschall.com>  
  45.      */   
  46.        
  47.     if  (*klen == APR_HASH_KEY_STRING) {  
  48.         for  (p = key; *p; p++) {  
  49.             hash = hash * 33 + *p;  
  50.         }  
  51.         *klen = p - key;  
  52.     }  
  53.     else  {  
  54.         for  (p = key, i = *klen; i; i--, p++) {  
  55.             hash = hash * 33 + *p;  
  56.         }  
  57.     }  
  58.     return  hash;  
  59. }  

[cpp:showcolumns] view plaincopy
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. APR_DECLARE_NONSTD(unsigned int) apr_hashfunc_default(const char *char_key,  
  2.                                                       apr_ssize_t *klen)  
  3. {  
  4.     unsigned int hash = 0;  
  5.     const unsigned char *key = (const unsigned char *)char_key;  
  6.     const unsigned char *p;  
  7.     apr_ssize_t i;  
  8.       
  9.     /* 
  10.      * This is the popular `times 33' hash algorithm which is used by 
  11.      * perl and also appears in Berkeley DB. This is one of the best 
  12.      * known hash functions for strings because it is both computed 
  13.      * very fast and distributes very well. 
  14.      * 
  15.      * The originator may be Dan Bernstein but the code in Berkeley DB 
  16.      * cites Chris Torek as the source. The best citation I have found 
  17.      * is "Chris Torek, Hash function for text in C, Usenet message 
  18.      * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich 
  19.      * Salz's USENIX 1992 paper about INN which can be found at 
  20.      * <http://citeseer.nj.nec.com/salz92internetnews.html>. 
  21.      * 
  22.      * The magic of number 33, i.e. why it works better than many other 
  23.      * constants, prime or not, has never been adequately explained by 
  24.      * anyone. So I try an explanation: if one experimentally tests all 
  25.      * multipliers between 1 and 256 (as I did while writing a low-level 
  26.      * data structure library some time ago) one detects that even 
  27.      * numbers are not useable at all. The remaining 128 odd numbers 
  28.      * (except for the number 1) work more or less all equally well. 
  29.      * They all distribute in an acceptable way and this way fill a hash 
  30.      * table with an average percent of approx. 86%. 
  31.      * 
  32.      * If one compares the chi^2 values of the variants (see 
  33.      * Bob Jenkins ``Hashing Frequently Asked Questions'' at 
  34.      * http://burtleburtle.net/bob/hash/hashfaq.html for a description 
  35.      * of chi^2), the number 33 not even has the best value. But the 
  36.      * number 33 and a few other equally good numbers like 17, 31, 63, 
  37.      * 127 and 129 have nevertheless a great advantage to the remaining 
  38.      * numbers in the large set of possible multipliers: their multiply 
  39.      * operation can be replaced by a faster operation based on just one 
  40.      * shift plus either a single addition or subtraction operation. And 
  41.      * because a hash function has to both distribute good _and_ has to 
  42.      * be very fast to compute, those few numbers should be preferred. 
  43.      * 
  44.      *                  -- Ralf S. Engelschall <rse@engelschall.com> 
  45.      */  
  46.        
  47.     if (*klen == APR_HASH_KEY_STRING) {  
  48.         for (p = key; *p; p++) {  
  49.             hash = hash * 33 + *p;  
  50.         }  
  51.         *klen = p - key;  
  52.     }  
  53.     else {  
  54.         for (p = key, i = *klen; i; i--, p++) {  
  55.             hash = hash * 33 + *p;  
  56.         }  
  57.     }  
  58.     return hash;  
  59. }  

对函数注释部分的翻译:
这是很出名的times33哈希算法,此算法被perl语言采用并在Berkeley DB中出现.它是已知的最好的哈希算法之一,在处理以字符串为键值的哈希时,有着极快的计算效率和很好哈希分布.最早提出这个算法的是Dan Bernstein,但是源代码确实由Clris Torek在Berkeley DB出实作的.我找到的最确切的引文中这样说"Chris Torek,C语言文本哈希函数,Usenet消息<<27038@mimsy.umd.edu> in comp.lang.c ,1990年十月."在Rich Salz于1992年在USENIX报上发表的讨论INN的文章中提到.这篇文章可以在<http://citeseer.nj.nec.com /salz92internetnews.html>上找到.

33这个奇妙的数字,为什么它能够比其他数值效果更好呢?无论重要与否,却从来没有人能够充分说明其中的原因.因此在这里,我来试着解释一下.如果某人试 着测试1到256之间的每个数字(就像我前段时间写的一个底层数据结构库那样),他会发现,没有哪一个数字的表现是特别突出的.其中的128个奇数(1除 外)的表现都差不多,都能够达到一个能接受的哈希分布,平均分布率大概是86%.

如果比较这128个奇数中的方差值(gibbon:统计术语,表示随机变量与它的数学期望之间的平均偏离程度)的话(见Bob Jenkins的<哈希常见疑问>http://burtleburtle.net/bob/hash/hashfaq.html,中对平方 差的描述),数字33并不是表现最好的一个.(gibbon:这里按照我的理解,照常理,应该是方差越小稳定,但是由于这里不清楚作者方差的计算公式,以 及在哈希离散表,是不是离散度越大越好,所以不得而知这里的表现好是指方差值大还是指方差值小),但是数字33以及其他一些同样好的数字比如 17,31,63,127和129对于其他剩下的数字,在面对大量的哈希运算时,仍然有一个大大的优势,就是这些数字能够将乘法用位运算配合加减法来替 换,这样的运算速度会提高.毕竟一个好的哈希算法要求既有好的分布,也要有高的计算速度,能同时达到这两点的数字很少.

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:333379次
    • 积分:4286
    • 等级:
    • 排名:第7050名
    • 原创:25篇
    • 转载:484篇
    • 译文:1篇
    • 评论:17条
    最新评论