生成全周期/全周期随机数或排列类似于LCG但没有奇数/偶数

and*_*ora 8 random algorithm numerical-methods

我希望生成一个伪随机数/置换,它在一个范围内"占据"一个完整的周期或整个周期.通常,"线性同余发生器"(LCG)可用于生成此类序列,使用如下公式:

X = (a*Xs+c) Mod R
Run Code Online (Sandbox Code Playgroud)

其中Xs是种子,X是结果,a和c是相对的素数常数,R是最大值(范围).

(通过完整周期/完整周期,我的意思是可以选择常数,使得任何X在一些随机/置换序列中仅出现一次,并且将在0到R-1或1到R的范围内).

LCG几乎满足了我的所有需求.我对LCG的问题是奇数/偶数结果的非随机性,即:对于种子Xn,结果X将交替奇数/偶数.

问题:

  1. 有没有人知道如何创造类似的东西,不会交替奇/偶?

  2. 我相信可以建立'复合LCG',但我没有细节.有人可以举一个这个CLCG的例子吗?

  3. 是否有替代公式可能符合上述细节和下面的约束?

约束:

  1. 我想要一些基于种子的简单公式.即:为了获得下一个数字,我提供种子并获得置换序列中的下一个"随机数".具体来说,我不能使用预先计算的数组.(见下一点)
  2. 序列绝对必须是'全周期/完整周期'
  3. 范围R可能是几百万甚至32比特/ 40亿.
  4. 计算不应该溢出并且有效/快速,即:没有大的指数或几十个乘法/除法.

  5. 序列不一定非常随机或安全 - 我不需要加密随机性(但如果可行则可以使用它),只需要"好"随机性或明显随机性,没有奇数/偶数序列.

任何想法都赞赏 - 提前感谢.

更新:理想情况下,Range变量可能不是2的精确幂,但在任何一种情况下都应该有效.

bti*_*lly 9

琐碎的解决方案.请用LCG R比你想的范围更大一些,两者的黄金a,并c在该范围内的某处随机的.如果它给出的数字大于您想要的数字,请再次迭代,直到您回到范围内.

数字输出将没有特别简单的模式mod 2,3,5等,直到任何素数小于你使用的素数.

如果你想要的范围很大,那么最接近的较大的素数只会是一个较小的量,所以你很少需要调用它两次.例如,如果您想要的范围是十亿,那么您可以使用1000000007作为素数,并且您需要跳过少于0.000001%的额外数字.

我通过访问http://primes.utm.edu/curios/includes/primetest.php并输入数字直到我得到一个素数来找到这个素数.我有点幸运.n结束的几率1, 3, 7, 9是大约2.5/log(n)是十亿,大约12%,所以我有点幸运在4次尝试后找到这个数字.但不是那么幸运 - 我发现它有3次尝试,平均而言我应该需要8次.

编辑:这个随机数发生器可以有一个更短的周期.请参阅@dzugaru的说明.

  • 你实际上不能这样做,因为素数`m`和任意`a`和`c`不满足Hull-Dobell定理,大概是规则2。尝试a = 2,c = 2,m = 5,周期是m - 1,而不是 m。看到这个谈话 https://en.wikipedia.org/wiki/Talk:Linear_congruential_generator#Rules_for_the_maximum_period (2认同)

Pet*_* G. 3

如果奇数/偶数交替是您唯一的问题,请保持状态更改计算不变。在使用每个输出之前,您可以将低位移出或交换位。

编辑:

使用位交换(固定模式)变体,您将继续生成整个周期。

初始LCG的伪代码:

function rand
   state := update(state)
   return state
Run Code Online (Sandbox Code Playgroud)

包括交换的 LCG 伪代码:

function rand2
   state := update(state) -- unchanged state computation
   return swapped(state)  -- output swapped state
Run Code Online (Sandbox Code Playgroud)

  • 不确定这是否明智,因为我可能会失去序列的“完整周期”排列属性。生成全周期序列是一个严格的约束。 (2认同)