如何将范围内的数字映射到相同范围内的另一个没有碰撞的数字?

时间:2017-07-08 00:35:39

标签: function random hash

实际上我正在寻找的是一个函数f(x),它输出到一个预定义的范围。调用f(f(x))也应该有效。该函数应该是循环的,因此调用调用次数等于范围大小的f(f(...(x)))应该给出原始数字,并且f(x)不应该是时间相关的并且总是给出相同的输出

虽然我可以看到获取所有可能值的列表并将其混洗会给我一些接近我想要的东西,如果我可以简单地将值一次插入函数中,我会更喜欢它,以便我不必一次计算整个范围。

我研究过Minimal Perfect Hash函数但是找不到不使用外部库的函数。我可以使用它们,但我宁愿不这样做。

如果需要实际范围来帮助回答我的问题,我认为它不需要大于[0, 2^24-1],但起始值和结束值并不重要。

2 个答案:

答案 0 :(得分:1)

您可能需要查看Linear Congruential Generator。您应该查看全周期生成器(例如,m = 2 24 ),这意味着参数应满足Hull-Dobell定理。

  

调用f(f(x))也应该有效。

应该有效

  

调用次数等于范围的大小应该给你原始数字

是的,对于参数满足Hull-Dobell定理的LCG,你将获得一次完整的周期,并且“m + 1”调用会让你回到你开始的地方。 这种LCG的周期恰好等于m

  

不应该是时间依赖的,并且总是会给出相同的输出

LCG是O(1)算法,它是100%可重复的

LCG也是可逆的,通过扩展的Euclid算法,检查Reversible pseudo-random sequence generator了解详情

答案 1 :(得分:0)

最小的完美哈希函数是矫枉过正的,你所要求的只是一个函数f,

  1. 双射,
  2. “循环”(即f N = f)
  3. 对于以这种方式呈现周期性的排列,其顺序必须除以N(或 N,但这种方式只是划分N的特殊情况)。这反过来意味着子周期的阶数的LCM必须除N.一种方法是只有一个“子”循环的阶数N.对于两个N的幂,它也很容易有很多一些其他二阶幂的小周期。一般排列不一定满足循环要求,当然它们是双射的,但子循环次序的LCM可能超过N.

    在下文中,我将保留所有减少模N的隐式。不失一般性,我会假设范围从0开始并上升到N-1,其中N是范围的大小。

    对于一般N,我唯一能想到的就是f(x) = x + c gcd(c, N) == 1。 GCD条件确保只有一个周期,必须具有N阶。

    对于2的力量N我有更多灵感:

    • f(x) = cx其中c是奇数。双射因为gcd(c, N) == 1所以c具有模乘法逆。 c N = 1,因为φ(N)= N / 2(因为N是2的幂)所以c φ(N) = 1(欧拉定理)
    • f(x) = x XOR c其中c < N。平凡的双射和平凡循环,周期为2,除以N.
    • f(x) = clmul(x, c)其中c为奇数,clmul为无进位乘法。双射因为任何奇c都有一个无进位乘法逆。有两个幂周期长度(小于N)所以它除N.我不知道为什么。这是一个奇怪的问题,但它有一些像x ^ (x << k)这样的特殊情况。通过对称,“镜像”版本也可以使用 例如x ^ (x >> k)
    • f(x) = x >>> k其中>>>位旋转。显然是双射的,并且f N (x)= x >>> Nk,其中Nk mod N = 0所以无论k是什么,它都会一直旋转回未旋转的位置。