【问题标题】:31-bit Bijective (Perfect) Hash algorithm31 位双射(完美)哈希算法
【发布时间】:2019-09-21 07:05:40
【问题描述】:

我需要什么

我需要一种产生双射输出的算法。我有一个 31 位输入,需要一个伪随机 31 位输出。

我的考虑

CRC 在其位宽内是双射的。

我在 Google 上查看过,可以找到这方面的多项式,但找不到表格或算法。

谁能指出我正确的方向?

我需要一个使用多项式 0x737e312b 的 CRC-31 算法,或者任何能满足我需要的双射函数。

注意

我找到了以下代码,但很遗憾我没有编译和运行它的工具。

【问题讨论】:

  • 所以你想对输入进行随机排列?
  • 您可以使用任何双射函数。您是在问存在哪些双射函数,或者哪个更好,或者如何实现一个,还是什么?
  • 您可以将输入与任意 31 位随机数进行异或。
  • 或者,你可以乘以一个(奇数)素数 mod 2**31
  • 好吧,试试吧! (只需 15 分钟左右)

标签: algorithm hash crc perfect-hash bijection


【解决方案1】:

对于任何哈希函数hash,你可以这样做:

function bijectiveHash31(int val) {
    val &= 0x7FFFFFFF; //make sure it's 31 bits
    for (int i=0; i<5; ++i) {
        // the high bits affect the low bits
        val ^= hash(val>>15) & 32767;
        // rotate bits
        val = ((val&32767)<<16) | ((val>>15)&65535);
    }
    return val;
}

这是一个 Feistel 结构,它构成了许多密码的基础:https://en.wikipedia.org/wiki/Feistel_cipher

如果您需要它快速而不需要它超级好,那么这可以正常工作:

function bijectiveHash31(int val) {
    val = ((val*RANDOM_ODD_NUMBER) + RANDOM_NUMBER) & 0x7FFFFFFF;
    val ^= (val>>15);
    val ^= (val>>8);
    return val;
}

在这两种情况下,弄清楚如何撤消每个基本操作并不是困难,这表明整个散列是双射的。如果您需要帮助确定乘法,请参阅https://en.wikipedia.org/wiki/Modular_multiplicative_inverse

【讨论】:

  • 另一种确保它是双射的(没有冲突)的方法是,您可以遍历所有可能的输入,并为每个输出在 256 MiB 位字段中设置一个位。最后,检查是否设置了所有位。使用速度相当快的编程语言(C、Java 等),这只需几秒钟。
  • 将第二种算法用作第一种算法的hash 函数会产生特别令人印象深刻的结果。
  • 仅供参考,我实现了 64、48、44、32、16 位版本here。但不是 31 位。
猜你喜欢
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 2016-12-30
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
  • 2011-11-11
  • 2016-06-23
相关资源
最近更新 更多