【问题标题】:Why are Knuth, CLRS hash functions not sufficient为什么 Knuth、CLRS 哈希函数不够用
【发布时间】:2018-03-31 03:18:48
【问题描述】:

很容易证明,给定一组未知分布的键,我们无法构造一个函数,以这些键作为输入,输出均匀分布的值。

因此,我们会研究用于未知分布的通用哈希函数。

Knuth 建议利用无理数的非重复数字 - 最显着的黄金比例 - 以便在表格范围内均匀分布键。

CLRS 建议再次简单地将键 mod 取一个大素数,以便在表范围内大致均匀分布键,并分解重复模式。

在这两种情况下,目标似乎都是平均分配密钥。

但是,当查看像 Murmur2、SeaHash 等这样的解决方案时,他们似乎在确保“蝴蝶般”的效果上付出了很多努力:给定一个密钥,更改任何一位都有很好的机会改变每一位在哈希中。

为什么这种行为是可取的? TAOCP 和 CLRS 中提出的这些解决方案有什么缺点?

如果期望的行为是分解输入键集中的任何模式,那么这里隐含的假设是表现出 any 类型模式的键集更有​​可能在野外?这合理吗?

对不起,如果我不准确。

编辑:不需要具有加密强度。目的是尽量减少冲突。

【问题讨论】:

  • 这个问题最好在cs.stackexchange.com
  • 这取决于您使用哈希函数的目的。如果你想隐藏原始信息(例如密码),那么最好不要通过观察两个哈希的相似性来得出原始信息的结论。
  • @martinstoeckli 查看编辑

标签: hash


【解决方案1】:

我对此不是 100% 确定,但这可能是不同作者在不同情况下做出不同假设的产物。

Knuth 在 TAoCP 中的工作是在任何其他书籍或哈希函数被开发之前完成的。当时,Knuth 在某种意义上开创了如何分析和思考不同算法和数据结构的道路。当时,“使用某种方案将东西分配到桶中”的想法是众所周知的,但没有人认真考虑过如何最好地选择该方案。他的方法在数学上简单而优雅,并且在当代(1970 年代)硬件上运行迅速。总的主题是“如果你要根据某个函数进行分配,这里有一个非常好用且简单的函数,并且背后有一个很好的理论。”

Knuth 的第一篇分析数据结构或算法的论文 IIRC 是关于哈希表的。他在哈希码是均匀随机的假设下进行了分析,并表明在这些假设下哈希表表现良好。

不过,正如您所提到的,很明显,如果您选择任何固定的哈希函数,您将得到退化的输入案例。一群人开始思考如何处理这个问题,许多人尝试了从可用哈希函数池中随机选择一个哈希函数的想法。在 1970 年代后期,Wegman 发表了一篇题为 Universal Classes of Hash Functions 的论文,其中概述了一个正式的数学定义,即散列函数家族成为可供选择的一类好的散列函数意味着什么。这篇论文包含了一个证明,证明通用哈希函数族的预期冲突数量很少,这使得它们非常适合链式哈希表。

第一版 CLRS 于 1990 年出版,结合了 Knuth 对线性探测的分析(假设是真正的随机哈希码)和使用通用哈希对链式哈希表的分析。换句话说,它承认你在选择散列函数时必须小心(没有一个固定函数总是有效的,所以看看通用散列),但也会在假设你有一个“足够好的”散列函数的情况下做一些数学运算。

(后来的理论发展包括具有里程碑意义的论文“为什么简单散列函数起作用”,解释了为什么弱散列函数与输入分布中的少量熵相结合本质上就像真正的随机函数一样,后来的一些工作表明 5-您只需要独立的哈希函数就可以在线性探测表中获得非常好的性能。)

上述所有工作都在 Theoryland 进行,其目标是建立良好的数学框架来分析数据结构,并为实践中的方法提出具体建议,以获得良好的分布和效率。

然后是真实世界,从业者并不总能得到数学,而且数学往往落后于从业者所做的事情。

如果您查看大多数关于散列函数的工作,许多散列函数假定您正在处理可以以有意义的方式轻松分解为整数单元的数据。但真实数据并不总是以这种方式很好地分解。或者你可能有一种像 C++、Java、Python 等这样的语言,其中每个对象都有“一个”哈希码,它是与之关联的 哈希码,而不是理论人们推荐的拥有可用的哈希函数。

在这样的情况下,尝试构建一个哈希函数并不是不合理的,它 (1) 评估速度非常快,(2) 可以跨同一程序或多台机器的不同运行,以及 (3)在实践中工作“足够好”,人们不会抱怨。这就是你得到像 MurmurHash 之类的哈希函数的地方——它们非常非常好地满足了这个需求。假设您没有针对对抗性选择的输入工作,那么这些类型的哈希函数就可以了。

有趣的是,我们现在看到了 Knuth 的复兴 乘法哈希函数。允许您将不同哈希函数组合在一起的库,例如 Boost 的 hash_combine,使用该技术在给定多个现有哈希作为输入的情况下提供确定性但广泛传播的哈希码。

总结一下:

  • 很多这些差异都是历史性的。 Knuth 为如何分析散列函数建立了理论基础,并考虑了具有单个散列函数的情况。后来关于通用散列的工作为使用散列函数类提供了不同的视角和框架。

  • 理论与实践之间总是存在差距。对于非对抗性情况,像 MurmurHash 这样的非随机散列简单、快速且运行良好。与单个整数值相比,它们也适用于可变长度输入。

【讨论】:

  • 这是一个彻底的答案。也许这句话总结得最好:“然后是现实世界,从业者并不总是得到数学,而数学往往落后于从业者所做的事情”。另外,非常感谢您将我推荐给“为什么简单的哈希函数工作”一文。
猜你喜欢
  • 2016-07-30
  • 2012-08-05
  • 1970-01-01
  • 2015-04-12
  • 2015-04-29
  • 2021-07-19
  • 2018-10-13
  • 1970-01-01
  • 2019-08-01
相关资源
最近更新 更多