【问题标题】:What are the disadvantages of hashing function using multiplication method使用乘法的散列函数有什么缺点
【发布时间】:2014-10-02 18:37:15
【问题描述】:

几乎所有教科书和 CS 课程都引用了两种实现哈希函数的基本方法:

  1. 除法,我们简单地做k mod m,基本上选择m作为素数,不太接近2的幂。
  2. 乘法,我们将 k 与一些在 0 到 1 之间精心挑选的无理数(Knuth 建议使用基于黄金比例的数)相乘,取乘积的小数部分并使用所需数量的最高有效位来自它。

大多数教科书和课程都列举了方法 1 的几个缺点,包括它很昂贵并且事情取决于 m。但是,我从未见过任何教科书或课程提到方法 2 的单一缺点。

这使得方法 2 更可取。另外,方法 2 在现代计算机上可以非常有效地消除浮点运算。所以看起来方法 2 是毫无疑问的赢家,没有人应该谈论方法 1。但显然情况并非如此。事实上,我从未见过方法 2 用于任何实际实现。所以它确实有一些缺点。

问题是它们是什么,为什么尽管方法 1 有缺点,但它的使用频率更高?

【问题讨论】:

    标签: algorithm hash hashtable


    【解决方案1】:

    除法与需要素数表大小的哈希表算法结合使用 - 例如,使用双哈希或QHash 的开放寻址,当您无论如何都需要按表大小划分键或哈希值以获得索引。

    当表大小是2的幂时,乘法方法是合适的,那么从哈希中获取索引可以实现为按位与运算,因此通过键计算表索引的整个路径,乘法散列,是非常快。你可以通过searching for magic constant 2654435769 on Github探索一些实际的实现。

    最近有一种趋势是使用MurmurHash3雪崩过程代替乘法:

    int hash = key;
    hash ^= (hash >> 16);
    hash *= 0x85ebca6b;
    hash ^= (hash >> 13);
    hash *= 0xc2b2ae35;
    hash ^= (hash >> 16);
    // see this code and the version for 64 bits here:
    // https://smhasher.googlecode.com/svn/trunk/MurmurHash3.cpp
    

    因为它只是有点慢,但被认为对错误的密钥分配更健壮。这就是为什么您可能会产生错误(或正确?)印象,即乘法方法很少被不公平地使用。

    【讨论】:

    • 谢谢。虽然这个答案很有见地,但它确实没有回答核心问题:乘法方法似乎在所有方面都比除法方法更好,包括你不再局限于选择素数 m 的事实。是的,杂音哈希应该更昂贵,但基本的乘法方法不是。为什么有人应该使用除法?
    • 我想我在第一段中回答了这个问题。一些算法要求表大小为素数。即使您使用任何其他散列函数,您必须在此之后执行昂贵的整数除法,以获得表中的索引。鉴于此,直接划分 (int) 键会更简单,无需预先散列,因为这种划分本身会产生可接受的良好分布。
    猜你喜欢
    • 2010-10-19
    • 2012-06-28
    • 2012-06-10
    • 2015-08-22
    • 1970-01-01
    • 2014-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多