【问题标题】:Looking for a Hash Function /Ordered Int/ to /Shuffled Int/寻找散列函数 /Ordered Int/ 到 /Shuffled Int/
【发布时间】:2023-03-12 09:05:01
【问题描述】:

我正在寻找可以将有序整数索引值更改为随机哈希索引的恒定时间算法。如果它是可逆的,那就太好了。我需要每个索引的哈希键都是唯一的。我知道这可以通过在大文件中查找表格来完成。 IE。创建所有整数的有序集,然后随机打乱它们并以随机顺序写入文件。然后,您可以在需要时将它们读回。但这需要寻找一个大文件。我想知道是否有一种简单的方法可以根据需要使用伪随机生成器来创建序列?

Generating shuffled range using a PRNG rather than shufflinganswer by erikkallen 的线性反馈移位寄存器看起来是正确的。我刚刚尝试过,但它会产生重复和孔洞。

问候 大卫·艾伦·芬奇

【问题讨论】:

  • 我认为这里没有足够的信息来提出一个好的解决方案。你需要散列多少个整数?该整数列表中是否会有重复项?您的列表的值范围是多少?
  • 有序整数是否允许为负数?
  • 我打算使用 unsigned long 或 long long 的全部范围(即 32 位或 64 位)。
  • 只是好奇——“遗传算法”标签是如何出现的?
  • 我输入了 Algorithm,因为这与我所追求的相吻合。自动完成放入“遗传算法”。如果标签有误,我很乐意删除。

标签: c++ algorithm hash


【解决方案1】:

现在的问题是您是否需要一个真正随机的映射,或者只是一个“弱”排列。假设后者,如果您在 2 的补码算术上使用无符号 32 位整数(例如),乘以任何奇数是双射和可逆映射。当然 XOR 也是如此,因此您可以尝试使用一个简单的模式,例如

unsigned int hash(int x) {
   return (((x ^ 0xf7f7f7f7) * 0x8364abf7) ^ 0xf00bf00b) * 0xf81bc437;
}

这些数字没有什么神奇之处。所以你可以改变它们,它们甚至可以是随机的。唯一的问题是被乘数必须是奇数。而且您必须使用回滚计算(忽略溢出)。这可以倒过来。要进行反演,您需要能够计算出正确的互补被乘数 A 和 B,然后反演是

unsigned int rhash(int h) {
    return (((x * B) ^ 0xf00bf00b) * A) ^ 0xf7f7f7f7;
}

您可以用数学方法计算 A 和 B,但对您来说更简单的事情就是运行一个循环并搜索它们(即离线后)。

该方程使用 XOR 与乘法混合以使映射非线性。

【讨论】:

  • 有趣的是 A 和 B 不成反比 A=1/0x8364abf7 或者存在舍入问题。
  • 不不,从这个意义上说,它们不是倒数。它们是模 2**32 的有限乘法群的逆。它与有理数领域的倒数无关。
  • 我对前 100,000 个数字进行了快速运行,结果看起来不错且速度非常快。我希望明天有更多的时间用更多的数字来测试它。
  • 是的,它既好又快 :) 唯一的问题是最低位是相当线性的......但这很可能不会对您的应用程序造成伤害。如果你想打破它,你可以在第一次乘法后将 ((x>19)) 添加到方程中。反之亦然。
【解决方案2】:

您可以尝试构建一个合适的Feistel network。这些通常用于加密(例如 DES),但至少有 64 位,因此您可能需要自己构建一个适合您需要的。它们在构造上是可逆的。

【讨论】:

  • 我认为这是正确的答案,但我需要一些时间来弄清楚如何实施 Feistel 网络。
【解决方案3】:

假设您的目标是将分组值分布在整个范围内,
似乎以某种预定义的顺序洗牌可能会奏效。
即给定 8 位 ABCDEFGH,将它们排列为 EGDBHCFA 或类似的模式。

代码只是一个简单的掩码、移位和添加序列。

【讨论】:

  • 是的,我就是这么想的,但我希望可能会有更随机的东西。
【解决方案4】:

嗯...如果您有很多数字,您可以使用普通的 stl 列表,并按“随机”标准对其进行排序

bool
nonsort(int i, int j)
{
    return  random() & 31 >16 ? true : false;
}

std::list<int> li;
// insert elements
li.sort(nonsort);

然后,您可以使用普通迭代器获取所有整数。记得用 srand() 用时间或任何其他伪随机值初始化 random。

【讨论】:

  • 我不知道您可以通过排序来做到这一点,对于较小的值,我认为这将是一个很好的解决方案。但我正在考虑一个 unsigned long long 的大小,用于整个范围。
【解决方案5】:

对于这组约束确实没有解决方案。尝试将 32 位无符号散列为 32 位无符号,将给您带来冲突,除非您执行一些简单的操作,例如 1 对 1 映射。每个数字都有自己的哈希值。

【讨论】:

    猜你喜欢
    • 2014-07-14
    • 1970-01-01
    • 2020-10-22
    • 2013-04-06
    • 2012-07-28
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 2015-11-29
    相关资源
    最近更新 更多