如今的普通硬盘早就到了 TB 级别了,为了装满这么大的硬盘只能用视频数据了。
普通数据很难搞到那么大,如果用垃圾数据或者某些数据不断复制,则结果是不准确的。
那么就看看视频数据吧,我随便找了三段长度不等的视频做了下统计
One: 1035228194 Zero: 1045177454
One: 2579804653 Zero: 2578664979
One: 6665438504 Zero: 6664059608
第一段里0略多,后两段 1 略多,初步结论就是基本差不多,具体哪个多看运气。
数bit这事太烧CPU,我笔记本都发烫了,不想测试更多了。
import struct, os filename, count_one, count_zero = 'example.txt', 0, 0 for current_byte in list(open(filename,'rb').read()): count_one += bin(struct.unpack("B",current_byte)[0]).count('1') count_zero = os.path.getsize(filename) * 8 - count_one print 'One: ' + str(count_one) + ' times
Zero: ' + str(count_zero) + ' times
One/Zero: ' + str(float(count_one)/float(count_zero))
我也写了个程序来统计1和0出现的数量,Python版,6行实现。
一次全载入内存,空间换时间,毕竟固态硬盘再强,随机读写性能也比不过内存,也省得分块读取了了。
程序GitHub地址:
Python-Binary-Statistics/statistics.py at master · lincanbin/Python-Binary-Statistics · GitHub以英文版圣经为例:
One: 13937005 times
Zero: 17550939 times
One/Zero: 0.794088851884
[Finished in 2.7s]
Python英文官方文档5. Built-in Types:
One: 327325 times
Zero: 396891 times
One/Zero: 0.82472265685
[Finished in 0.2s]
美国国宝Justin Bieber知名歌曲《Baby》的歌词
One: 7090 times
Zero: 9134 times
One/Zero: 0.776220713817
[Finished in 0.1s]
大家可以看到1与0的比值是一直在0.8附近波动的,这是因为英语字母是以ASCII码在计算机中保存的,大写字母的ASCII码范围是从01000001到01011010,小写字母则是从01100001到01111010。ASCII码都是以0开头,并且英语文章中中字母并不是等概率出现。根据对大部分文章的统计,可以得到英文字母使用概率表。
英文字母使用频率表:(%)
A 8.19 B 1.47 C 3.83 D 3.91 E 12.25 F 2.26 G 1.71
H 4.57 I 7.10 J 0.14 K 0.41 L 3.77 M 3.34 N 7.06
O 7.26 P 2.89 Q 0.09 R 6.85 S 6.36 T 9.41
U 2.58 V 1.09 W 1.59 X 0.21 Y 1.58 Z 0.08
可以看到概率是各不相同的,不过上表缺少了空格以及标点。用这些概率乘上对应 ASCII码的 1与0的比 并累加就可以得到这个结果,应该是0.8附近(我其实没算……从实际测试来看应该是这个数值)
然后是中文,UTF-8编码24位表示一个汉字
史诗巨作《斗破苍穹》UTF-8版:
One: 70866992 times
Zero: 65263776 times
One/Zero: 1.0858549159
[Finished in 10.8s]
经常写正则表达式的朋友肯定知道UTF-8中汉字对应的区块是:
[u4e00-u9fa5]
换成二进制也就是100111000000000 - 1001111110100101。
第一个字是: 11100100 10111000 10000000 (一)
最后一个字是: 11101001 10111110 10100101 (龥)
汉字数量比较多,各个汉字的权重实际上影响不是特别大。因为UTF-8汉字编码前4位必然是1110,并且汉字二进制编码范围如上所述。所以实际中,UTF-8汉语文字里 1与0的比 会略高于1,根据我自己的语料库来看,在1.10左右。
GBK正则表达式匹配则是这样写的:
[x80-xFF]
但是这个范围还包含了全角标点,同理,这里同样给出参考:
史诗巨作《斗破苍穹》GBK版:
One: 50675085 times
Zero: 42257995 times
One/Zero: 1.19918337347
[Finished in 7.5s]
至于EXE,因为编译出来的结果常常会有大片的、连续为零的冗余段,实际有不少exe一零比会远远低于1,例如世界上最好的语言的解释器的前端:
One: 200601 times
Zero: 409703 times
One/Zero: 0.489625411579
[Finished in 0.1s]
这是java.exe
One: 595247 times
Zero: 931601 times
One/Zero: 0.638950580774
[Finished in 0.2s]
EXE这个因程序而异,实际各个程序间区别很大。
剩下的例如JPG、MP3、RAR等等带压缩文件的1 & 0则是接近等概率分布。
因为它们是压缩文件,二元信源中信息熵:
图像为倒U型,当P=0.5时取得信息熵H(X)最大。而信息熵越大,表示占用二进制位越长,因此就可以表达更多符号。数据压缩正是基于这一点,当这个文件趋近于无法再压缩时,信息熵趋近于1。
因为目前的压缩算法都比较优秀了,所以这些带压缩文件的 1和0的比值 都是趋近于1的。
例如这个 Fate/Zero 的字幕文件的压缩包:(压缩一般来说还是需要比较大的文件才有明显的效果,这个文件尺寸算是中等,可以作为参考)
One: 1820004 times
Zero: 1805588 times
One/Zero: 1.00798410269
[Finished in 0.5s]
上文中的php.exe压缩后的php.rar:
One: 134836 times
Zero: 134892 times
One/Zero: 0.999584853068
[Finished in 0.2s]
但是我不想跑整个硬盘,太伤,跑坏了我价值连城的固态硬盘你们赔我?反正你的硬盘内容肯定跟我不一样,我这里大片大片One/Zero = 0.8的项目代码,还有大片大片的 One/Zero ≈ 1.0的 MP3、小本子、片子。
总体来说大部分文件1&0还是趋向于等概率分布,因为文件压缩技术随着计算机性能的提升已经得到了广泛的推广,但是实际比值多少还是跟硬盘文件比例有关,因人而异,要看你硬盘里主要文件类型是什么。