字元形式的md5串的各個字母分布均勻嗎

2021-06-10 02:46:26 字數 3045 閱讀 7683

今天在想這個問題,乙個目錄下有太多(20萬)個以md5串作為檔名的檔案,想把他們按相同的字首放到子目錄中,假如字首的長度是1個字母,就只需要建立16(6個字母+10個數字)個父目錄,但是這能保證每個目錄下的檔案個數大致相當嗎,md5串的各個字母的分布是不是等概率的呢,考慮這樣幾個md5串:

cfcd208495d565ef66e7dff9f98764da

c4ca4238a0b923820dcc509a6f75849b

c81e728d9d4c2f636f067f89cc14862c

eccbc87e4b5ce2fe28308fd9f2a7baf3

a87ff679a2f3e71d9181a67b7542122c

e4da3b7fbbce2345d7772b0674a318d5

1679091c5a880faf6fb5e6087eb1b2dc

8f14e45fceea167a5a36dedd4bea2543

c9f0f895fb98ab9159f51fd0297e236d

45c48cce2e2d7fbdea1afc51c7c6ad26

是選第乙個字母作為目錄好還是選最後乙個字母好呢(或者是選中間的其他字母),為了解決這個問題,我大致計算了一下md5串各個位上字母的熵,程式如下(**中的libjade是我的python實用工具庫  ):

#coding:utf8

from libjade import *

from math import log

def entropy(lst):

st=set(lst)

ps={}

l=len(lst)

for i in st:

ps[i]=float(lst.count(i)) / l

return sum([-p * log(p, 2) for p in ps.values()])

if __name__=='__main__':

lsts={}

for i in range(300000):

s=md5(str(i))

for j in range(0, 32):

if not j in lsts:

lsts[j]=[s[j]]

else:

for j in range(0, 32):

print j, entropy(lsts[j])

執行結果顯示,熵幾乎都是4,說明每個位置的字母都大概是均勻分布的:

0 3.9999445219

1 3.9999799341

2 3.99997465219

3 3.99992966376

4 3.99997557506

5 3.99997854535

6 3.99995146435

7 3.9999726059

8 3.99996545565

9 3.9999705381

10 3.99996871359

11 3.99995660577

12 3.99995196213

13 3.99995732855

14 3.99994707575

15 3.99995717605

16 3.99995565124

17 3.99996349489

18 3.99997235641

19 3.99997430926

20 3.99996398965

21 3.99994457348

22 3.9999782949

23 3.99998414043

24 3.9999664288

25 3.99994949642

26 3.99994869626

27 3.99997557227

28 3.99997027123

29 3.99993962184

30 3.99993844981

31 3.99995679387

當md5串足夠多的時候,隨便選哪個字母作為目錄都能大致均勻的將檔案雜湊到各個目錄中。但是考慮到作業系統在乙個目錄中查詢檔案時,也是在一棵由檔名構成的類似b+樹的資料結構中查詢目標檔名,我們知道字串匹配時從左到右進行的,如果乙個目錄中的檔名字首都想同,那麼在b+樹種查詢時,從根節點到目標節點之間途徑的每個節點每至少比較完字首部分才能確定兩個字串不同,這樣就做了大量的無用比較,而相反的,如果乙個目錄中的檔名僅僅是字尾相同, 那麼比較前面的部分就可以快速區分檔名是否不同,相同的字尾僅僅會在b+樹中找到目標節點時比較一次,這樣就節省了大量的無用的比較次數。

因此得出結論,雖然md5串中各個字母都是分布均勻的,但是盡量使用後面的字母作為目錄名進行大量檔案的雜湊會更好一些。

如果檔案數量太多,使用最後乙個字母進行雜湊僅僅只能保證每個目錄中的平均檔案數是原來總數的16分之一。使用更多的字母來雜湊可以繼續按照每個字母16倍的速度縮小每個目錄下雜湊的檔案數。如果使用2個字母,將產生256個資料夾,3個字母4096個,4個字母65536個,個人感覺最多使用3個字母做同級目錄是比較合適的。如果3個字母雜湊後每個字目錄中檔案還是太多,則可以繼續進行雜湊。各種情況典型的目錄結構如:

da/cfcd208495d565ef66e7dff9f98764da

da/c4ca4238a0b923820dcc509a6f7583da

da/64/cfcd208495d565ef66e7dff9f98764da

da/64/c4ca4238a0b923820dcc509a6f7564da

da/64/7/cfcd208495d565ef66e7dff9f98764da

da/64/7/c4ca4238a0b923820dcc509a6f7764da

da/64/87/cfcd208495d565ef66e7dff9f98764da

da/64/87/c4ca4238a0b923820dcc509a6f8764da

posted on 五月 29, 2012 at 8:46 上午

MD5的簡單學習,鑰匙串

c語言中的md5,寫法主要是 1.建立md5摘要 2.初始化摘要 3.更新md5的摘要 4,結束md5 oc中的md5,略有不同.鑰匙串部分 鑰匙串實在mac os8.7 ios7之後被加入的 鑰匙串可以包含多種資料資訊,密碼 私鑰 電子證書 加密筆記 它是基於硬體的,將資料儲存在加密晶元中 存放在...

shell中計算字串的md5值

echo 123 md5sum ba1f2511fc30423bdbb183fe33f3dd0f php r echo md5 123 202cb962ac59075b964b07152d234b70 兩者的md5值不一致,於是有很多有趣的解法 1 mysql解法 mysql select md5 ...

shell下取得字串的md5值

今日群裡問起乙個問題 echo 123 md5sum ba1f2511fc30423bdbb183fe33f3dd0f php r echo md5 123 202cb962ac59075b964b07152d234b70 兩者的md5值不一致,於是有很多有趣的解法 1 mysql解法 mysql ...