Hash碰撞概率


計算Hash沖突的概率

雖然已經很多可以選擇的Hash函數,但創建一個好的Hash函數仍然是一個活躍的研究領域。一些Hash函數是快的,一些是慢的,一些Hash值均勻地分布在值域上,一些不是。對於我們的目的,讓我們假設這個Hash函數是非常好的。它的Hash值均勻地分布在值域上。

在這種情況下,對於一個輸入集合生成的Hash值是非常像生成一個隨機數集合。我們的問題轉化為如下: 
        給K個隨機值,非負而且小於N,他們中至少有個相等的概率是多少? 
實際上我們求這個問題的對立問題更加簡單:他們都不相同的概率是多少?無論這個對立問題的結果是多少,我們用1減去對立問題的結果就得到原問題的結果。

對於一個值域為N的Hash值,假設你已經挑選出一個值。之后,剩下N-1個值是不同於第一個值的,因此,對於第二次隨機生成不同第一個數的概率為N/N-1. 
簡而言之,有N個不同的數,你第一次挑選出某個,然后繼續從N個數中挑選,那只要不是選到和第一次一樣的那個數一樣就不一樣嘍,所以概率為N-1/N。 
之后就是第三次挑選,第三次挑選出的第三個數要求不同於前兩個數,所以概率就為N-1/N*N-2/N. 
一般的,隨機生成K個數,他們都不相同的概率為: 
這里寫圖片描述 
計算機中,對於K很大的時候計算很麻煩,幸運的是,上面的表達式近似於 
這里寫圖片描述 
這個會更快得計算,我們如何知道這是一個好的近似。我們看一下分析過程,使用泰勒公式和epsilon-delta proof,這個誤差趨於0當N增大的時候。或者,更簡單,你可以計算2者的值然后比較他們,運行下面的python代碼,你會感覺到這個近似是多么准確:

import math
N = 1000000
probUnique = 1.0
for k in xrange(1, 2000):
    probUnique = probUnique * (N - (k - 1)) / N
    print k, 1 - probUnique, 1 - math.exp(-0.5 * k * (k - 1) / N)

好的,這個奇妙的表達式作為我們每個值都不一樣的結果,然后我們用1減去得到Hash沖突的概率 
這里寫圖片描述 
這是一個 N=2^32的圖,它說明了使用32bit的Hash值的沖突概率,當Hash數是77163時,發生碰撞的可能為50%,這是有價值的。而且注意無論N區任意值都會得到一個類似S曲線的圖。 
這里寫圖片描述

簡化表達式

這是非常有趣的,我們的表達式是1-e^-x這種形式,下面近似這僅僅在X較小的時候誤差非常小,1/10或更小: 
這里寫圖片描述 
換句話說,這個表達式非常好的近似於它自己的指數,實際上x越小,越准確,所以小的沖突概率,我們能使用這個簡化表達式 
這里寫圖片描述 
這實際上是一個非常方便的表示。因為它避免了一些在原表達式中的精度問題。浮點型數字在非常接近1的時候表示不是很好。

此外,如果N遠大於K,K和K-1並沒有什么大區別。所以我們可以更加化簡為:K^2/2N

 

 

 

參考:   

Hash碰撞概率

Hash算法的碰撞概率


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM