【问题标题】:Evenly distributed hash function均匀分布的哈希函数
【发布时间】:2010-09-28 19:47:14
【问题描述】:

我需要一个哈希函数,它需要几个(例如 2 或 3 个)无符号整数作为输入,并返回一个介于 -1 和 +1 之间的浮点值。

这些返回值的集合必须均匀分布。函数的输出序列必须看起来是随机序列,即使输入数字是连续的。 而且越快越好,我经常这样称呼它。

我希望这不是太多要求:S...

【问题讨论】:

    标签: algorithm random hash


    【解决方案1】:

    Murmurhash 是一个非常好(强大)且快速的哈希函数,已经对其进行了一些严格的测试。

    http://sites.google.com/site/murmurhash/

    虽然它本身并不专用于整数,但可以快速调整它以实现这一点。如果您的单词没有按顺序排列在记忆中,我有这样一个替代表述可能对您更方便:

    #define MURMURHASH2A_R 24 #define MURMURHASH2A_MULTIPLIER 0x5bd1e995 #define MURMURHASH2A_SEED 2166136261U // 没有种子建议,所以使用 FNV32_OFFSET_BASIS #define murmurhash2a_init(h) 做 { h = MURMURHASH2A_SEED; } 而 (0) #define murmurhash2a_update(h,word) \ 做 { \ u_int mmh2ak = (word) * MURMURHASH2A_MULTIPLIER; \ mmh2ak ^= mmh2ak >> MURMURHASH2A_R; \ mmh2ak *= MURMURHASH2A_MULTIPLIER; \ h *= MURMURHASH2A_MULTIPLIER; \ h ^= mmh2ak; \ } 而 (0) #define murmurhash2a_final(h) \ 做 { \ h ^= h >> 13; \ h *= MURMURHASH2A_MULTIPLIER; \ h ^= h >> 15; \ } 而 (0) u_int 哈希; murmurhash2a_init(哈希); murmurhash2a_update(hash,firstint); murmurhash2a_update(hash,secondint); [...] murmurhash2a_final(哈希);

    显然这是返回 0-2^32-1。 murmurhash 网站上有一个 64 位版本。在一定范围内将整数转换为浮点数作为练习(除法)留给读者。

    【讨论】:

      【解决方案2】:

      您可以为此类任务采用标准方案:(a0 + Q*a1 + Q^2*a2 + Q^3*a3 + ...) % M 其中M 是一个非常大的素数,Q 是您选择的系数。
      一旦你在[0, M) 范围内有足够的随机散列,将其转换为浮点数[-1, 1] 是微不足道的。

      或者您可以删除 % M 并允许发生整数溢出,尽管我不确定它有多安全(从“均匀分布”的角度来看)。

      函数的输出序列必须看起来是随机序列,即使输入数字是连续的。
      为此,您可以在表达式中使用 ai*ai 而不是 ai。无论如何,这是Java中的简单实现。

      double hash(int... a) {
          int Q = 433494437;
          int result = 0;
          for (int n : a) {
              result = result * Q + n * n;
          }
          result *= Q;
          return (double) result / Integer.MIN_VALUE;
      }
      

      即使对于连续的数字,输出看起来也是随机的。您还可以使用 64 位整数以获得更高的精度。

      【讨论】:

      • 这个很好用,也比我想象的简单多了!非常感谢。
      • @Nikita Rybak:这会因为平方而产生碰撞。实际上,每个散列都会创建它们,但是在这里您太容易获得它们了。对于 1 元组序列(-1), (0), (1),结果确实不是随机的。供电到 3 或类似 (n + 12345) * n 可能会做得更好。
      猜你喜欢
      • 2016-02-07
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-24
      • 1970-01-01
      • 2011-04-04
      • 1970-01-01
      • 2020-04-04
      相关资源
      最近更新 更多