1、哈希算法
摘要算法 == 哈希算法 == 散列算法
输入输出:把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
digest = f(data)
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
Python提供了常见的摘要算法,如MD5,SHA1
MD5是生成结果是固定的128 bit,SHA1的结果是160 bit。(这里廖雪峰老师的原文应该是笔误吧,“SHA1的结果是160 bit字节”,混淆了bit和byte)
要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文)。
可以用在:
(1)检测内容是否篡改(篡改后哈希值一般不再相同)
(2)在不存储明文口令的情况下验证用户口令。
特殊地:不同的data映射到相同的digest,这是可能发生的,因为f做的是无限空间到有限空间的映射,必然有碰撞。
2、哈希算法的一个特点:如果散列值不相同,放心,原始输入绝对不相同。
如果两个散列值相同,两个输入值很可能是相同的,但注意,也可能不同(碰撞)
3、布隆过滤
前几篇文章没有讲清楚(或者直接说有错),比如从维基百科跳到这里:这个图没问题Hash和Bloom Filterwww.sigma.me这个图没问题
这个说法似乎有问题,而且过于复杂了
上文说到m位的位向量,我以为这里的位是计算机中的bit,所以进一步误以为m位中的每一位都只能是0或者1,进一步对x到1个点的映射过程产生了困惑……现在知道了,计算机里的“位”和生活中的“位”是不同的概念,写作时应当加以区分。
搜到这里清楚一点:https://china.googleblog.com/2007/07/bloom-filter_7469.htmlchina.googleblog.com
其实就是:
无论给的输入是什么,都会被映射成m个对象中的1个。但是因为有碰撞,所以如果x和y的映射结果相同也不能证明x == y。为了能够判别x和y是不是一样,升级为再来几个映射函数,如果几个映射函数的结果都相同,那么基本判定 x == y。
3、布隆过滤的误判重
是的,本来我也不想深入看布隆过滤的原理,直接用同事现成的代码。
但应用时出现了问题,就是本来不是重复的被判别为重复而没有推送,数量还不少!
为此我检查了我的特征值、代码、日志……都没看到问题,一问同事,才知道确实有误判重复的可能性,虽然很低……
现在问题就在这里了,虽然概率低但是我的数据量大啊。
注意到判重的错误 发生的情况:不相同 而误判为 相同。
本来判重就是依靠无限 到 有限的映射,假设说这个有限是100个对象。我任何的输入都会被映射到这100个对象中的任意1个,那么如果我有101个对象,必然会有至少2个映射到同一个对象,判断为重复(先不考虑多个映射方法),这个判断结果当然是错误的。所以,对象的数量100个肯定太少了,越多越好,比如如果是10000个,那么100个对象要有其中2个映射到同一对象的概率就会小很多,如果是100000000个,那么就更小了。
另一方面,如果已经是任何输入会被映射到有限的100000000个对象,即对象数量已经很大……但如果之前已经有不同的输入通过映射已经占据了其中的99999999个对象,再来一个随机新输入,其映射的值落在其中的可能性相当大,所以说发生误判的可能也是很大(为什么说是误判?因为这时候判定为重复的概率是99999999/100000000,判定为不重复的可能性为1/100000000,而输入是无限集合,有这个规模真正重复的概率应该远远小于不重复的概率)
综上,误判概率变大,原因大概有这么3个:有限集合里的对象个数太少
映射方法的数目不够
已存在的对象值相对对象个数来说太多
代码跟这里很像:
明天看看代码具体怎么实现,有没有不合适的地方。
【0710 更】
当时第二天看好像判重程序没有问题,好像是我日志看得不对。
最近测试关上了过滤,下次待验证。