哈希算法

Hash,就是把任意長度的輸入,通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉換是一種壓縮映射,也就是,散列值的空間通常遠小於輸入的空間,不同的輸入可能會散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。數學表述爲:h = H(M) ,
其中H( )--單向散列函數,M--任意長度明文,h--固定長度散列值。  

 在信息安全領域中應用的Hash算法,還需要滿足其他關鍵特性:   
   第一當然是單向性(one-way),從預映射,能夠簡單迅速的得到散列值,而在計算上不可能構造一個預映
射,使其散列結果等於某個特定的散列值,即構造相應的M=H-1(h)不可行。這樣,散列值就能在統計上唯一的
表徵輸入值,因此,密碼學上的 Hash 又被稱爲"消息摘要(messagedigest)",就是要求能方便的將"消息"進
行"摘要",但在"摘要"中無法得到比"摘要"本身更多的關於"消息"的信息。 
  
   第二是抗衝突性(collision-resistant),即在統計上無法產生2個散列值相同的預映射。給定M,計算上
無法找到M',滿足H(M)=H(M') ,此謂弱抗衝突性;計算上也難以尋找一對任意的M和M',使滿足H(M)=H(M')
,此謂強抗衝突性。要求"強抗衝突性"主要是爲了防範 所謂"生日攻擊(birthdayattack)",在一個10人的團
體中,你能找到和你生日相同的人的概率是2.4%,而在同一團體中,有2人生日相同的概率是11.7%。類似的,
當預映射的空間很大的情況下,算法必須有足夠的強度來保證不能輕易找到"相同生日"的人。   

   第三是映射分佈均勻性和差分分佈均勻性,散列結果中,爲 0 的 bit 和爲 1 的 bit ,其總數應該大致
相等;輸入中一個 bit的變化,散列結果中將有一半以上的 bit 改變,這又叫做"雪崩效應(avalanche effect)";
要實現使散列結果中出現 1bit的變化,則輸入中至少有一半以上的 bit 必須發生變化。其實質是必須使輸入
中每一個 bit 的信息, 儘量均勻的反映到輸出的每一個 bit上去;輸出中的每一個 bit,都是輸入中儘可能
多 bit 的信息一起作用的結果。Damgard 和 Merkle定義了所謂“壓縮函數(compression function)”,就是
將一個固定長度輸入,變換成較短的固定長度的輸出,這對密碼學實踐上Hash函數的設計產生了很大的影響。
Hash函數就是被設計爲基於通過特定壓縮函數的不斷重複“壓縮”輸入的分組和前一次壓縮處理的結果的過程,
直到整個消息都被壓縮完畢,最後的輸出作爲整個消息的散列值。儘管還缺乏嚴格的證明,但絕大多數業界的
研究者都同意,如果壓縮函數是安全的,那麼以上述形式散列任意長度的消息也將是安全的。任意長度的消息
被分拆成符合壓縮函數輸入要求的分組,最後一個分組可能需要在末尾添上特定的填充字節,這些分組將被順
序處理,除了第一個消息分組將與散列初始化值一起作爲壓縮函數的輸入外,當前分組將和前一個分組的壓縮
函數輸出一起被作爲這一次壓縮的輸入,而其輸出又將被作爲下一個分組壓縮函數輸入的一部分,直到最後一
個壓縮函數的輸出,將被作爲整個消息散列的結果。MD5 和 SHA1 可以說是目前應用最廣泛的Hash算法,而它
們都是以MD4 爲基礎設計的。
設計高效算法往往需要使用Hash鏈表,常數級的查找速度是任何別的算法無法比擬的,Hash鏈表的構造和衝突
的不同實現方法對效率當然有一定的影響,然而Hash函數是Hash鏈表最核心的部分,下面是幾款經典軟件中使
用到的字符串Hash函數實現,通過閱讀這些代碼,我們可以在Hash算法的執行效率、離散性、空間利用率等方
面有比較深刻的瞭解。
下面分別介紹幾個經典軟件中出現的字符串Hash函數。

●PHP中出現的字符串Hash函數
static unsigned long hashpjw(char *arKey, unsigned int nKeyLength)
{
    unsigned long h = 0, g;
    char *arEnd=arKey+nKeyLength; 

    while (arKey < arEnd) {
        h = (h << 4) + *arKey++;
        if ((g = (h & 0xF0000000))) {
            h = h ^ (g >> 24);
            h = h ^ g;
        }
    }

    return h;
}


OpenSSL中出現的字符串Hash函數

unsigned long lh_strhash(char *str)
{
    int i,l;
    unsigned long ret=0;
    unsigned short *s; 

    if (str == NULL) return(0);
    l=(strlen(str)+1)/2;
    s=(unsigned short *)str; 

    for (i=0; i<l; i++)
        ret^=(s[i]<<(i&0×0f));

    return(ret);
} 



/* The following hash seems to work very well on normal text strings 
* no collisions on /usr/dict/words and it distributes on %2^n quite 
* well, not as good as MD5, but still good. 
*/
unsigned long lh_strhash(const char *c)
{
    unsigned long ret=0;
    long n;
    unsigned long v;
    int r; 

    if ((c == NULL) || (*c == ‘\0′))
        return(ret);

    /*
    unsigned char b[16]; 
    MD5(c,strlen(c),b); 
    return(b[0]|(b[1]<<8)|(b[2]<<16)|(b[3]<<24)); 
    */ 

    n=0×100;
    while (*c)
    {
        v=n|(*c);
        n+=0×100;
        r= (int)((v>>2)^v)&0×0f;
        ret=(ret(32-r));
        ret&=0xFFFFFFFFL;
        ret^=v*v;
        c++;
    } 

    return((ret>>16)^ret);
}


MySql中出現的字符串Hash函數

 
#ifndef NEW_HASH_FUNCTION 

/* Calc hashvalue for a key (區分大小寫)*/
static uint calc_hashnr(const byte *key,uint length)
{
    register uint nr=1, nr2=4; 

    while (length––)
    {
        nr^= (((nr & 63)+nr2)*((uint) (uchar) *key++))+ (nr << 8);
        nr2+=3;
    } 

    return((uint) nr);
} 

/* Calc hashvalue for a key, case indepenently (不區分大小寫) */
static uint calc_hashnr_caseup(const byte *key,uint length)
{
    register uint nr=1, nr2=4; 

    while (length–)
    {
        nr^= (((nr & 63)+nr2)*((uint) (uchar) toupper(*key++)))+ (nr << 8);
        nr2+=3;
    } 

    return((uint) nr);
}

#else
/* 
* Fowler/Noll/Vo hash 
* 
* The basis of the hash algorithm was taken from an idea sent by email to the 
* IEEE Posix P1003.2 mailing list from Phong Vo ([email protected]) and 
* Glenn Fowler ([email protected]). Landon Curt Noll ([email protected]) 
* later improved on their algorithm. 
* 
* The magic is in the interesting relationship between the special prime 
* 16777619 (2^24 + 403) and 2^32 and 2^8. 
* 
* This hash produces the fewest collisions of any function that we’ve seen so 
* far, and works well on both numbers and strings. 
*/

//(區分大小寫) uint calc_hashnr(const byte *key, uint len) { const byte *end=key+len; uint hash; for (hash = 0; key < end; key++) { hash *= 16777619; hash ^= (uint) *(uchar*) key; } return (hash); } //(不區分大小寫) uint calc_hashnr_caseup(const byte *key, uint len) { const byte *end=key+len; uint hash; for (hash = 0; key < end; key++) { hash *= 16777619; hash ^= (uint) (uchar) toupper(*key); } return (hash); } #endif

另一個經典字符串Hash函數

 
unsigned int hash(char *str)
{
    register unsigned int h;
    register unsigned char *p; 

    for(h=0, p = (unsigned char *)str; *p ; p++)
        h = 31 * h + *p; 

    return h;
}


MurmurHash算法:高運算性能,低碰撞率,由Austin Appleby創建於2008年,現已應用到Hadoop、libstdc++、nginx、libmemcached等開源系統。2011年Appleby被Google僱傭,隨後Google推出其變種的CityHash算法。

官方網站:https://sites.google.com/site/murmurhash/
https://github.com/aappleby/smhasher.git
MurmurHash算法,自稱超級快的hash算法,是FNV的4-5倍。官方數據如下:

OneAtATime – 354.163715 mb/sec
FNV – 443.668038 mb/sec
SuperFastHash – 985.335173 mb/sec
lookup3 – 988.080652 mb/sec
MurmurHash 1.0 – 1363.293480 mb/sec
MurmurHash 2.0 – 2056.885653 mb/sec


unsigned long long MurmurHash64B ( const void * key, int len, unsigned int seed )
{
	const unsigned int m = 0x5bd1e995;
	const int r = 24;
 
	unsigned int h1 = seed ^ len;
	unsigned int h2 = 0;
 
	const unsigned int * data = (const unsigned int *)key;
 
	while(len >= 8)
	{
		unsigned int k1 = *data++;
		k1 *= m; k1 ^= k1 >> r; k1 *= m;
		h1 *= m; h1 ^= k1;
		len -= 4;
 
		unsigned int k2 = *data++;
		k2 *= m; k2 ^= k2 >> r; k2 *= m;
		h2 *= m; h2 ^= k2;
		len -= 4;
	}
 
	if(len >= 4)
	{
		unsigned int k1 = *data++;
		k1 *= m; k1 ^= k1 >> r; k1 *= m;
		h1 *= m; h1 ^= k1;
		len -= 4;
	}
 
	switch(len)
	{
	case 3: h2 ^= ((unsigned char*)data)[2] << 16;
	case 2: h2 ^= ((unsigned char*)data)[1] << 8;
	case 1: h2 ^= ((unsigned char*)data)[0];
			h2 *= m;
	};
 
	h1 ^= h2 >> 18; h1 *= m;
	h2 ^= h1 >> 22; h2 *= m;
	h1 ^= h2 >> 17; h1 *= m;
	h2 ^= h1 >> 19; h2 *= m;
 
	unsigned long long h = h1;
 
	h = (h << 32) | h2;
 
	return h;
} 

參數說明:

key:字符串

len:字符串長度

seed:種子,最好用一個質數

seed : 0xEE6B27EB  一個40億內的質數


轉載自:http://blog.sina.com.cn/s/blog_7595a7e20102vjl4.html


哈稀函數按照定義可以實現一個僞隨機數生成器(PRNG),從這個角度可以得到一個公認的結論:哈希函數之間性能的比較可以通過比較其在僞隨機生成方面的比較來衡量。

一些常用的分析技術,例如泊松分佈可用於分析不同的哈希函數對不同的數據的碰撞率(collision rate)。一般來說,對任意一類的數據存在一個理論上完美的哈希函數這個完美的哈希函數定義是沒有發生任何碰撞,這意味着沒有出現重複的散列在現實中很難找到一個完美的哈希散列函數,而且這種完美函數的趨近變種在實際應用中的作用是相當有限的。在實踐中人們普遍認識到,一個完美哈希函數的哈希函數,就是在一個特定的數據集上產生的的碰撞最少哈希的函數。

現在的問題是有各種類型的數據,有一些是高度隨機的,有一些有包含高緯度的圖形結構,這些都使得找到一個通用的哈希函數變得十分困難,即使是某一特定類型的數據,找到一個比較好的哈希函數也不是意見容易的事。我們所能做的就是通過試錯方法來找到滿足我們要求的哈希函數。可以從下面兩個角度來選擇哈希函數:

1.數據分佈

 一個衡量的措施是考慮一個哈希函數是否能將一組數據的哈希值進行很好的分佈。要進行這種分析,需要知道碰撞的哈希值的個數,如果用鏈表來處理碰撞,則可以分析鏈表的平均長度,也可以分析散列值的分組數目。

2.哈希函數的效率

另個一個衡量的標準是哈希函數得到哈希值的效率。通常,包含哈希函數的算法的算法複雜度都假設爲O(1),這就是爲什麼在哈希表中搜索數據的時間複雜度會被認爲是"平均爲O(1)的複雜度",而在另外一些常用的數據結構,比如圖(通常被實現爲紅黑樹),則被認爲是O(logn)的複雜度。

一個好的哈希函數必修在理論上非常的快、穩定並且是可確定的。通常哈希函數不可能達到O(1)的複雜度,但是哈希函數在字符串哈希的線性的搜索中確實是非常快的,並且通常哈希函數的對象是較小的主鍵標識符,這樣整個過程應該是非常快的,並且在某種程度上是穩定的。

在這篇文章中介紹的哈希函數被稱爲簡單的哈希函數。它們通常用於散列(哈希字符串)數據它們被用來產生一種在諸如哈希表的關聯容器使用的key這些哈希函數不是密碼安全的很容易通過顛倒和組合不同數據的方式產生完全相同的哈希值。



哈希方法學


哈希函數通常是由他們產生哈希值的方法來定義的,有兩種主要的方法:

1.基於加法和乘法的散列

這種方式是通過遍歷數據中的元素然後每次對某個初始值進行加操作,其中加的值和這個數據的一個元素相關。通常這對某個元素值的計算要乘以一個素數。



 

2.基於移位的散列

和加法散列類似,基於移位的散列也要利用字符串數據中的每個元素,但是和加法不同的是,後者更多的而是進行位的移位操作。通常是結合了左移和右移,移的位數的也是一個素數。每個移位過程的結果只是增加了一些積累計算,最後移位的結果作爲最終結果。



 

 


哈希函數和素數

沒有人可以證明素數和僞隨機數生成器之間的關係,但是目前來說最好的結果使用了素數。僞隨機數生成器現在是一個統計學上的東西,不是一個確定的實體,所以對其的分析只能對整個的結果有一些認識,而不能知道這些結果是怎麼產生的。如果能進行更具體的研究,也許我們能更好的理解哪些數值比較有效,爲什麼素數比其他數更有效,爲什麼有些素數就不行,如果能用可再現的證明來回答這些問題,那麼我們就能設計出更好的僞隨機數生成器,也可能得到更好的哈希函數。

圍繞着哈希函數中的素數的使用的基本的概念是,利用一個素質來改變處理的哈希函數的狀態值,而不是使用其他類型的數。處理這個詞的意思就是對哈希值進行一些簡單的操作,比如乘法和加法。這樣得到的一個新的哈希值一定要在統計學上具有更高的熵,也就是說不能有爲偏向。簡單的說,當你用一個素數去乘一堆隨機數的時候,得到的數在bit這個層次上是1的概率應該接近0.5。沒有具體的證明這種不便向的現象只出現在使用素數的情況下,這看上去只是一個自我宣稱的直覺上的理論,並被一些業內人士所遵循。

決定什麼是正確的,甚至更好的方法和散列素數的使用最好的組合仍然是一個很有黑色藝術沒有單一的方法可以宣稱自己是最終的通用散列函數。最好的所能做的就是通過試錯演進和獲得適當的散列算法,以滿足其需要的統計分析方法。



位偏向

位序列發生器是純粹隨機的或者說在某種程度上確定性的,可以按照一定的概率產生某種狀態或相反狀態的比特,這個概率就是位偏向。在純粹隨機的情況下,產生高位或者低位的位偏向應該是50%。

然後在僞隨機產生器中,算法將決定在產生器在最小輸出模塊的位偏向。



 

假設一個PRNG的產生8作爲其輸出塊。出於某種原因,MSB始終是設置爲高,MSB的位偏向將是100%的概率置高這一結論是,即使有256個PRNG的產生可能的值,小於128將永遠不會產生。簡單起見,假設其他位正在生成純粹是隨機的,那麼平等的機會,128和255之間的任何值將產生,但是在同一時間,有0%的機會,一個小於128的值會產生

所有PRNGs,無論是雜湊函數,密碼,msequences或其他任何產生比特流的產生器都會有這樣一個位偏向大多數PRNGs他們將嘗試收斂位偏向到一個確定值流密碼就是一個例子,而其他產生器在不確定的位偏向下效果更好。

混合位序列加擾是一種產生在一個共同的平等流位偏向的方法。雖然我們必須要小心,以確保他們不會混合至發散偏向。密碼學中的一個混合使用的形式被稱爲雪崩,這就是一個位塊使用另一個塊來替換或置換混合在一起,而另一塊產生與其他快混合的輸出。

正如下圖中顯示的,雪崩過程始於一個或多個二進制數據塊。對數據中的某些位操作通常是一些輸入敏感位減少位邏輯)生產第i數據。然後重複這個過程是第i數據,以生成一個i+1層數據,是當前層的位數小於或等於的位數

這一反覆的過程導致一個依靠之前數據所有位的位應該指出的是,下圖是一個單純概括,雪崩過程不一定這一進程的唯一形式。


 

 


 

各種形式的哈希

 

哈希是一個在現實世界中將數據映射到一個標識符的工具,下面是哈希函數的一些常用領域:

1.字符串哈希

在數據存儲領域,主要是數據的索引和對容器的結構化支持,比如哈希表。

2.加密哈希

用於數據/用戶覈查和驗證。一個強大的加密哈希函數很難從結果再得到原始數據加密哈希函數用於哈希用戶的密碼,用來代替密碼本身存在某個服務器撒很難過加密哈希函數也被視爲不可逆的壓縮功能,能夠代表一個信號標識大量數據,可以非常有用的判斷當前的數據是否已經被篡改(比如MD5),也可以作爲一個數據標誌使用,以證明通過其他手段加密文件的真實性

3.幾何哈希

這個哈希表用於計算機視覺領域,爲任意場景分類物體的探測。

最初選擇過程涉及一個地區或感興趣的對象。從那裏使用,如Harris角檢測器(HCD的),尺度不變特徵變換(SIFT)或速成的強大功能(衝浪組功能仿射提取被視爲代表仿射不變特徵檢測算法表示對象或地區。這一套有時被稱爲宏觀功能或功能的星座。發現的功能的性質類型的對象或地區被列爲它可能仍然是可能的匹配兩個星座的特點,即使可能有輕微的差異如丟失或異常特徵)兩集。星座,然後說是功能分類設置。
哈希值是計算星座的特性這通常是由最初定義一個地方的哈希是爲了居住空間中完成- 在這種情況下,散列值一個多層面的價值,定義的空間正常化。再加上計算的哈希值另一個進程,決定了兩個哈希值之間的距離是必要的過程-一個距離測量是必需的,而不是一個確定性的平等經營者由於星座哈希值計算可能的差距問題也因爲簡單歐氏距離度量本質上是無效的,其結果是自動確定特定空間的距離度量已成爲學術界研究的活躍領域處理這類空間的非線性性質。
幾何散列包括各種汽車分類的重新檢測任意場景的目的,典型的例子。檢測水平可以多種多樣,從檢測是否是車輛,到特定型號車輛,在特定的某個車輛。
4.布隆過濾器

布隆過濾器允許一個非常大範圍內的值被一個小很多的內存鎖代表在計算機科學,這是衆所周知的關聯查詢,並在關聯容器的核心理念。
Bloom Filter的實現通過多種不同的hash函數使用,也可通過允許一個特定值的存在一定的誤差概率會員查詢結果的。布隆過濾器保證提供的是,對於任何會員國的查詢就永遠不會再假陰性,但有可能是假陽性。假陽性的概率可以通過改變控制布隆過濾器,並通過不同的hash函數的數量所使用的表的大小。
隨後的研究工作集中在散列函數和哈希表以及Mitzenmacher的布隆過濾器領域。建議對這種結構,在數據散列最實用的用法有助於哈希函數熵,理論成果締結一項最佳的布隆過濾器(一個提供給定一個最低的進一步導致假陽性的可能性表的大小反之亦然)提供假陽性的概率定義用戶可以建造最多也作爲兩種截然不同的兩兩獨立的哈希散列函數已知功能,大大提高了查詢效率的成員
布隆過濾器通常存在於諸如拼寫檢查器,字符串匹配算法,網絡數據包分析工具和網絡/ Internet緩存的應用程序。

常用的哈希函數

通用的哈希函數庫有下面這些混合了加法和一位操作的字符串哈希算法。下面的這些算法在用法和功能方面各有不同,但是都可以作爲學習哈希算法的實現的例子。(其他版本代碼實現見下載

1.RS 
從Robert Sedgwicks的 Algorithms in C一書中得到了。我(原文作者)已經添加了一些簡單的優化算法,以加快散列過程。
[java] view plaincopy
  1. public long RSHash(String str)  
  2.     
  3.       int     378551 
  4.       int     63689 
  5.       long hash 0 
  6.       for(int 0str.length(); i++)  
  7.        
  8.          hash hash str.charAt(i);  
  9.             b;  
  10.        
  11.       return hash;  
  12.     
 
2.JS
Justin Sobel寫的一個位操作的哈希函數。
[c-sharp] view plaincopy
  1. public long JSHash(String str)  
  2.     
  3.       long hash 1315423911;  
  4.       for(int 0; str.length(); i++)  
  5.        
  6.          hash ^= ((hash << 5) str.charAt(i) (hash >> 2));  
  7.        
  8.       return hash;  
  9.     
 
3.PJW 
該散列算法是基于貝爾實驗室的彼得J溫伯格的的研究。在Compilers一書中(原則,技術和工具)建議採用這個算法的散列函數的哈希方法。
[java] view plaincopy
  1. public long PJWHash(String str)  
  2.     
  3.       long BitsInUnsignedInt (long)(4 8);  
  4.       long ThreeQuarters     (long)((BitsInUnsignedInt  34);  
  5.       long OneEighth         (long)(BitsInUnsignedInt 8);  
  6.       long HighBits          (long)(0xFFFFFFFF<< (BitsInUnsignedInt OneEighth);  
  7.       long hash              0 
  8.       long test              0 
  9.       for(int 0str.length(); i++)  
  10.        
  11.          hash (hash << OneEighth) str.charAt(i);  
  12.          if((test hash HighBits)  != 0 
  13.           
  14.             hash (( hash (test >> ThreeQuarters)) (~HighBits));  
  15.           
  16.        
  17.       return hash;  
  18.     
 
4.ELF 
和PJW很相似,在Unix系統中使用的較多。
[java] view plaincopy
  1. public long ELFHash(String str)  
  2.     
  3.       long hash 0 
  4.       long    0 
  5.       for(int 0str.length(); i++)  
  6.        
  7.          hash (hash << 4str.charAt(i);  
  8.          if((x hash 0xF0000000L) != 0 
  9.           
  10.             hash ^= (x >> 24);  
  11.           
  12.          hash &= ~x;  
  13.        
  14.       return hash;  
  15.     
 
5.BKDR
這個算法來自Brian Kernighan 和 Dennis Ritchie的 The C Programming Language。這是一個很簡單的哈希算法,使用了一系列奇怪的數字,形式如31,3131,31...31,看上去和DJB算法很相似。(參照我之前一篇博客,這個就是Java的字符串哈希函數)
[java] view plaincopy
  1. public long BKDRHash(String str)  
  2.     
  3.       long seed 131// 31 131 1313 13131 131313 etc..  
  4.       long hash 0 
  5.       for(int 0str.length(); i++)  
  6.        
  7.          hash (hash seed) str.charAt(i);  
  8.        
  9.       return hash;  
  10.     
 
6.SDBM
這個算法在開源的SDBM中使用,似乎對很多不同類型的數據都能得到不錯的分佈。
[java] view plaincopy
  1. public long SDBMHash(String str)  
  2.     
  3.       long hash 0 
  4.       for(int 0str.length(); i++)  
  5.        
  6.          hash str.charAt(i) (hash << 6(hash << 16hash;  
  7.        
  8.       return hash;  
  9.     
 
7.DJB
這個算法是Daniel J.Bernstein 教授發明的,是目前公佈的最有效的哈希函數。
[java] view plaincopy
  1. public long DJBHash(String str)  
  2.     
  3.       long hash 5381 
  4.       for(int 0str.length(); i++)  
  5.        
  6.          hash ((hash << 5hash) str.charAt(i);  
  7.        
  8.       return hash;  
  9.     
 
8.DEK
由偉大的Knuth在《編程的藝術 第三卷》的第六章排序和搜索中給出。
[java] view plaincopy
  1. public long DEKHash(String str)  
  2.     
  3.       long hash str.length();  
  4.       for(int 0str.length(); i++)  
  5.        
  6.          hash ((hash << 5(hash >> 27)) str.charAt(i);  
  7.        
  8.       return hash;  
  9.     
 
9.AP
這是本文作者Arash Partow貢獻的一個哈希函數,繼承了上面以旋轉以爲和加操作。代數描述:AP

 

[java] view plaincopy
  1. public long APHash(String str)  
  2.     
  3.       long hash 0xAAAAAAAA 
  4.       for(int 0str.length(); i++)  
  5.        
  6.          if ((i 1== 0 
  7.           
  8.             hash ^= ((hash << 7str.charAt(i) (hash >> 3));  
  9.           
  10.          else  
  11.           
  12.             hash ^= (~((hash << 11str.charAt(i) (hash >> 5)));  
  13.           
  14.        
  15.       return hash;  
  16.     
 

 

這裏有一個關於這些算法的評測,可以稍微看看,自己也可以簡單測試下,我在VSM試驗中的測試,這些算法沒有太大的性能差異,可能是數據量較小的緣故。


 

 

各版本哈希代碼下載

 

 





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章