我希望生成“占据”一个范围内的完整周期或完整周期的伪随机数/排列。通常,“线性同余生成器”(LCG) 可用于生成此类序列,使用的公式如下:
X = (a*Xs+c) Mod R
其中 Xs 是种子,X 是结果,a 和 c 是互质常数,R 是最大值(范围)。
(通过完整周期/完整周期,我的意思是可以选择常数,以便任何 X 在某个随机/排列序列中只出现一次,并且在 0 到 R-1 或 1 到 R 的范围内) .
LCG 几乎可以满足我的所有需求。我对 LCG 的问题是奇数/偶数结果的非随机性,即:对于种子 Xn,结果 X 将交替奇数/偶数。
问题:
有谁知道如何创建 类似的东西不会 交替奇数/偶数?
我相信“复合 LCG” 可以 build ,但我没有 细节。有人可以给一个 这个 CLCG 的例子?
是否有替代公式 可能满足上述细节和 约束低于?
约束:
- 我想要一些基于简单的东西 基于种子的配方。即:得到 下一个号码,我提供种子和 获取下一个“随机数” 置换序列。具体来说, 我不能使用预先计算的数组。 (见下几点)
- 顺序绝对必须是“全周期/全周期”
- 范围 R 可能是几百万 甚至 32 位/40 亿。
计算不应发生溢出并且高效/快速,即:没有大指数或数十次乘法/除法。
序列不必非常随机或安全 - 我不需要密码随机性(但如果可行的话可以使用它),只是“良好”的随机性或明显的随机性,不需要奇数/偶数序列。
任何想法表示赞赏 - 提前致谢。
更新:理想情况下,Range 变量可能不是 2 的精确幂,但在任何一种情况下都应该有效。
最佳答案
简单的解决方案。用 R
制作一个 LCG,它是一个比你想要的范围大一些的素数,并且 a
和 c
都在那个范围内随机。如果它给你的数字大于你想要的,再次迭代直到你回到范围内。
输出的数字不会有一个特别简单的模式 mod 2、3、5 等,直到小于您使用的素数的任何素数。
如果您想要的范围很大,那么最近的较大质数只会稍微大一点,因此您很少需要调用它两次。例如,如果您想要的范围是十亿,您可以使用 1000000007 作为素数,并且您需要跳过一个少于 0.000001% 的额外数字。
我通过转到 http://primes.utm.edu/curios/includes/primetest.php 找到了这个素数并输入数字直到我得到素数。我有点幸运。以 1, 3, 7, 9
结尾的 n
是素数的几率大约是 2.5/log(n)
,其中十亿是大约 12%,所以我很幸运,只尝试了 4 次就找到了这个数字。但没那么幸运——我试了 3 次就找到了,平均而言我应该需要 8 次。
编辑:这个随机数生成器的周期可以更短。请参阅@dzugaru 的注释。
关于algorithm - 生成类似于 LCG 但没有奇数/偶数的全周期/全周期随机数或排列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3583697/