• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >编程问答 > 为何哈希函数取余法要避免2的幂?

为何哈希函数取余法要避免2的幂?

作者:佚名 字体:[增加 减小] 来源:互联网 时间:2017-06-07

佚名通过本文主要向大家介绍了哈希函数,哈希函数算法,哈希函数值,哈希函数的特点,什么是哈希函数等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
问题:为何哈希函数取余法要避免2的幂?

解决方案1:

哈希函数的重要特性沙渺的答案也指出了,就是要尽量让输出等概率,从而降低碰撞的频率。不过剩下的条件我觉的不一定适用。从mod可以猜到,这里的哈希是给哈希表算数据该放到哪个bucket里的,而不是用来进行签名/密码保护的(md5, sha-1...)。所以不可预测,不可逆推等不是必要条件。

对一个用于加密的哈希函数来说,原值部分保持不变是非常失败的。不过对一个用在哈希表上的哈希函数,就不能用容易逆推什么的证明它失败了。理论上,若x的分布是平均的,那么maxM取值多少效果都一样好。假设x平均分布在[0, k * maxM],那么f(x)就会平均分布于[0, maxM]。从排除哈希碰撞的角度看,这已经是最优的分布了。

但是理论归理论,实际上maxM最好还得是个质数,因为x的分布在实际应用中很难做到平均分布,这时候maxM的取值就至关重要。首先不难看出maxM不能取2^t这种数,因为这样等同于把输入数据的高位截断了。如果恰好输入数据变化的只有高位。。。那就会悲剧。。。所有的数据都会被分配到一个桶。比如maxM=256,257%256=1,513%256=1,769%256=1……

再把之前的思路扩展一下,一个哈希函数若能保证在输入数据跟任何整数同余(不光只有2的幂)的情况下,都能避免大量碰撞,那就更好了。在Java的HashMap实现中(http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/HashMap.java?av=f#360),第368行就解释了通过高低位不断异或的方式打乱同余的规律,从而达到了抑制碰撞的效果。

但要是只能用题目中f(x) = x mod m这种形式呢?假设输入形式是a+k, 2a+k, 3a+k等等:

让X={ja+k | k,j为正整数}, x∈X
让b=gcd(a, m), c=a/b, d=m/b
(ja+k) mod m
=(ja mod m + k mod m) mod m
=[b(jc mod d + k mod m)] mod m
=b[(jc mod d + k mod m) mod d]
因为c和d互质,所以jc mod d的可能取值是d个。
而k mod m又是常数,所以整个等式的可能取值正好是d个。d=m/gcd(a, m)

由此看出f(x)只可能取maxM/gcd(maxM, a)这么多个值。a若跟maxM互质,取值范围就会最大化,哈希函数会达到不错的散布效果。
所以maxM是质数的话,a取多少都能保证良好散布啦。

以上简要写了下我对maxM为啥不能是2^t,而且一般是质数的理解,至于为啥不能接近2^t,我还是没法回答。初次在segmentfault上发言,有错误和不妥之处还请各位大牛多多指正。

解决方案2:

我觉得这个是从二进制的角度考虑的。接近2^i的种子,二进制表达时中间必然产生大段的0或1。

那么以10000000000011这个种子为例,把它翻n倍:

1000000000001100
 110000000001001
 100000000000110
  10000000000011

可以看到,如果种子过于接近2^i,那么无论如何翻倍,种子中间仍然会有大段的0或1。

取余运算的本质无非是个减去种子n倍的减法。那么做减法的时候,种子中间大段的0或1就会让哈希原值的中间一段,有非常大的可能性仍然保持原样。

哈希函数的本质目的就是混淆,原值的变化产生哈希值无规律、等概率、不可预测、不能逆推的变化为最佳。

如果做完哈希运算之后,哈希值和原值中间居然有一大段二进制位保持不变,那么这个哈希函数就可以说是失败到不能再失败了。


当然必须说明的是:简单取余这个哈希函数本来就是非常失败的。简单分析即可,不必深究,也不要在任何真正的产品代码中实用。


分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 哈希函数取余法除数为何要取质数?
  • 为何哈希函数取余法要避免2的幂?

相关文章

  • 2017-06-07 私有空间如何获取视频帧缩略图
  • 2017-06-07 scrapy如何处理验证码?
  • 2017-06-07 python抓取新浪网页时,有时候得不到HTML代码
  • 2017-06-07 七牛云存储如何上传相机返回的照片?
  • 2017-06-07 请问这段代码哪里出错了呢?
  • 2017-06-07 如何在Python中实现js的escape?
  • 2017-06-07 python爬虫(python)py2exe问题求助
  • 2017-06-07 对ruby感兴趣,打算学习一下,结果刚开始就遇到了问题。。。
  • 2017-06-07 判断NULL七牛用表单上传,返回null
  • 2017-06-07 Redis缓存Java对象的问题

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • (python)socketserver+ssl+daemon客服端连接问题!
    • (python)使用requests下载大文件,设置steam=True,如何确保文件被完整下载?
    • 分班问题(背包问题)?
    • Pandas的DataFrame数据转换
    • (shell)osx里面的/bin/[是做什么用的?
    • 帮忙:windows安装pywin32不成功
    • (python)为什么argparse输入变成数组
    • 原本在cmd中输在cmd输入命令式需要输入py文件和相关参数,PyCharm调试py程序时,参数怎么获取?
    • ejb问题
    • 如何做一个开源项目?

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有