2个整数间隔的非幂的混合函数

时间:2019-03-22 10:02:18

标签: math hash unsigned-integer

我正在寻找一个混合函数,该函数给出间隔<0,n)的整数,从同一间隔返回看起来随机的整数。间隔大小n通常为2的复合非幂。我需要功能是一对一的。它只能使用O(1)内存,强烈建议使用O(1)时间。我不太担心输出的随机性,但从外观上看,它应该足够随机(请参阅下一段)。

我想将此功能用作实时渲染器中的像素改组步骤,以选择渲染像素的顺序(输出将在固定时间后显示,如果尚未完成,这会给我带来很大的噪音)但快速的部分预览)。间隔大小n将是渲染中的像素数(n = 1920 * 1080 = 2073600是典型值)。该函数必须是一对一的,这样我就可以确保完成后每个像素都被精确渲染一次。

我已经看过hash prospector使用的可逆构造块,但是这些块主要是针对2范围的幂的。

我唯一想到的另一种方法是乘以大质数,但是它并不能提供特别好的随机输出。

这里还有哪些其他选择?

1 个答案:

答案 0 :(得分:1)

这是一种基于原始根对素数进行模运算的解决方案:

如果a是原始根mod p,则函数g(i) = a^i % p是小于p的非零元素的排列。这对应于Lehmer prng。如果为n < p,则可以得到0, ..., n-1的排列,如下所示:给定i在该范围内,请先加1,然后反复乘以a,得到结果mod { {1}},直到获得p元素为止,此时将返回结果-1。

要填充详细信息,this paper包含一个表,该表给出一系列素数(所有素数均接近<= n的幂)和选择的相应原始根,以便它们产生具有良好统计特性的生成器。这是该表的一部分,被编码为Python字典,其中的键是素数,原始根是值:

2

考虑到d = {32749: 30805, 65521: 32236, 131071: 66284, 262139: 166972, 524287: 358899, 1048573: 444362, 2097143: 1372180, 4194301: 1406151, 8388593: 5169235, 16777213: 9726917, 33554393: 32544832, 67108859: 11526618, 134217689: 70391260, 268435399: 150873839, 536870909: 219118189, 1073741789: 599290962} (在一定范围内,如果需要扩大该范围,请参阅本文),您可以找到最小的n,它可以工作:

p

一旦知道了def find_p_a(n): for p in sorted(d.keys()): if n < p: return p, d[p] 和匹配的n,以下函数就是p,a的排列:

0 ... n-1

进行快速测试:

def f(i,n,p,a):
    x = a*(i+1) % p
    while x > n:
        x = a*x % p
    return x-1

n = 2073600 p,a = find_p_a(n) # p = 2097143, a = 1372180 nums = [f(i,n,p,a) for i in range(n)] print(len(set(nums)) == n) #prints True 中的平均乘法数为f(),在这种情况下为p/n,并且永远不会超过1.011(或自{ {1}}不是2的精确幂。实际上,此方法与您的“乘以大质数”方法没有根本区别,但是在这种情况下,应更仔细地选择因子,并且有时有时需要多次乘法才能增加表面随机性。