字符形式的md5串的各个字母分布均匀吗

字符形式的md5串的各个字母分布均匀吗

字符形式的md5串的各个字母分布均匀吗

http://jadesoul.sinaapp.com/2012/05/29/%E5%AD%97%E7%AC%A6%E5%BD%A2%E5%BC%8F%E7%9A%84md5%E4%B8%B2%E7%9A%84%E5%90%84%E4%B8%AA%E5%AD%97%E6%AF%8D%E5%88%86%E5%B8%83%E5%9D%87%E5%8C%80%E5%90%97/


今天在想这个问题,一个目录下有太多(20万)个以md5串作为文件名的文件,想把他们按相同的前缀放到子目录中,假如前缀的长度是1个字母,就只需要创建16(6个字母+10个数字)个父目录,但是这能保证每个目录下的文件个数大致相当吗,MD5串的各个字母的分布是不是等概率的呢,考虑这样几个MD5串:

cfcd208495d565ef66e7dff9f98764da
c4ca4238a0b923820dcc509a6f75849b
c81e728d9d4c2f636f067f89cc14862c
eccbc87e4b5ce2fe28308fd9f2a7baf3
a87ff679a2f3e71d9181a67b7542122c
e4da3b7fbbce2345d7772b0674a318d5
1679091c5a880faf6fb5e6087eb1b2dc
8f14e45fceea167a5a36dedd4bea2543
c9f0f895fb98ab9159f51fd0297e236d
45c48cce2e2d7fbdea1afc51c7c6ad26

是选第一个字母作为目录好还是选最后一个字母好呢(或者是选中间的其他字母),为了解决这个问题,我大致计算了一下md5串各个位上字母的熵,程序如下(代码中的libjade是我的python实用工具库 https://github.com/jadesoul/libjade ):

#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:
                                lsts[j].append(s[j])

        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 上午


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值