我对函数rand(x, y, seed)
感兴趣,它根据参数返回(伪)随机数,具有以下属性:
返回的值应取决于其3个参数,不取决于到目前为止调用rand
的次数。例如,假设这些调用,按此顺序:
rand(0, 0, 123) = 1 rand(0, 1, 123) = 2 rand(0, 2, 123) = 3
然后使用相同的参数调用rand
,但是以不同的顺序,我们应该得到相同的值。例如:
rand(0, 1, 123) = 2 rand(0, 2, 123) = 3 rand(0, 0, 123) = 1
该函数应具有良好的通常属性(体面,我真的不需要任何非常花哨的东西)PRNG:大周期,均匀分布等。返回适合有符号整数的正整数是好的。如果你愿意,它也可以更高。
如果它有帮助,我的种子将始终是以毫秒为单位的unix时间戳(如果以某种方式使其更容易,也可以以秒为单位)。所有参数都可以高达32位有符号整数,但在函数内部使用64位值不是问题。
我可以使用什么功能?
我的想法:
Perlin noise似乎做了我想要的一些事情,但我不知道它作为一个PRNG是多么合适,尤其是分布式的。我也不确定它的效率如何,因为我的(x, y)
参数会相当随机,我无法为所有参数预先计算它。
我还研究了以下功能:
p = 1400328593
rand(x, y, seed) = (x * x * seed + y * seed * seed + seed * x * y + seed) mod p
= (seed * (x * x + y * seed + x * y + 1)) mod p
似乎可以生成足够好的数字。基于我的(非常弱)测试,它们似乎也很好地分布。虽然测试期间比较困难,但我还没有这样做。
更新
以下是上述函数的Ent输出,其中time(NULL)
在C中作为种子,为(x, y) in {0 ... 999} x {0 ... 999}
生成了值:
熵=每字节3.312850位。
最佳压缩会减少此9207076字节文件的大小 58%。
9207076样品的卡方分布为229710872.43,和 随机将超过此值不到0.01%的时间。
数据字节的算术平均值为52.3354(127.5 =随机)。蒙特 Pi的Carlo值为4.000000000(误差27.32%)。串行 相关系数为0.036131(完全不相关= 0.0)。
这在实践中是否足够好(理论上,上述测试表明它根本不好),或者是否有一些众所周知的我应该使用的东西?
答案 0 :(得分:2)
听起来你想要一个哈希函数。选择一个安全的,如SHA1,如果它不是太低效,因为它保证具有良好的分布特性;否则,您可以使用常见的哈希函数,如FNV。只需使用种子和坐标作为输入数据,并将哈希作为随机值。
答案 1 :(得分:1)
您可以尝试使用Blum Blum Shub。它具有可以直接计算系列的第n个值的属性,这似乎适合您的情况。它需要三个参数,p,q和x0。 p和q是素数,x0对p和q都是相关的素数。所以你的参数x和y可用于找到第x和第y个素数,然后它们适用于p和q,然后你可以使用你的第三个参数为x0找到合适的值。这有点单调乏味,而Blum Blum Shub因为它是一个加密RNG而很慢,但是如果你真的不需要速度那么它就会起作用并且不会非常难以实现。
另一种方法是采用像CMWC这样的RNG,用x + y ^ i + seed ^(2i)填充生成器的第i个位置,运行生成器很少(可能是它存储的值的数量等于的次数),然后从中拉出一个值。