我正在以
为特色的环境中编写应用程序+
,-
,*
,/
和其余AND
或OR
这样的位操作。但由于一个补码,XOR
相当于减法而NOT
相当于否定。IF/THEN/ELSEIF/ELSE/IF
。理想情况下,我想要35或36位随机整数,但25位就足够了。
如果基于足够大的数字,linear congruential generator的天真实现会遇到溢出,并且当我使用较小的数字时,只产生少量的位。
所以我正在寻找一组数字 a,c,m ,它们将产生约束中的最大位数,或者合理地调整LCG以组合2个或更多号。
作为一个起点,这是我到目前为止所使用的:
*DEFINE NextRandom . min,max resultVar
* . This is a very shitty RNG. The numbers were never checked
* . for suitability for a long-period linear congruential generator.
* . But it yields numbers that look vaguely random.
*CLEAR rq
*CLEAR rr
*SET RandZ = RandZ * 169687 + 347011 . RandZ is a global var.
*DIVIDE RandZ BY 131072 GIVING rq, RandZ . Division yields a remainder
*DIVIDE RandZ BY 4 GIVING rq
*SET r0 = +[#,[#],1,1] . r0 = argument 'min'
*SET r9 = +[#,[#],1,2] . r9 = 'max'
*SET rd = r9 - r0 + 1
*DIVIDE rq BY rd GIVING rq, rr
*SET [#,[#],2,1] TO r0 + rr . return in 'resultVar'
*ENDDEFINE
如果有人关心,脚本语言是UNISYS 2200大型机操作系统EXEC 8中的SSG(符号流生成器)。
关键性:此RNG工作的应用程序生成测试数据。它不加密国家机密或核导弹代码。所以我们谈的是“很高兴”和“尽力而为”,而不是“关键任务”。我对改进感到高兴,但我不是在寻找最终的解决方案。
答案 0 :(得分:6)
有可能写出一个永远不会溢出的线性同余随机数发生器,正如Stephen K. Park和Keith W. Miller demonstrate在他们的论文中随机数发生器:好的很难查找:
function Random : real;
(* Integer Version 2 *)
const
a = 16807;
m = 2147483647;
q = 127773; (* m div a *)
r = 2836; (* m mod a *)
var
lo, hi, test : integer;
begin
hi := seed div q;
lo := seed mod q;
test := a * lo - r * hi;
if test > 0 then
seed := test
else
seed := test + m;
Random := seed / m
end;
这里 m 是2 ^ 31-1,但你可以改变它以产生36位数字。诀窍是将种子分成 hi 和 lo 部分,并通过对部分求和来生成最终的随机数。
如果您不喜欢,我的博客上有lots个随机数生成器。也许他们中的一个会做你想做的事。
答案 1 :(得分:1)
只是一个简单的想法,我不知道这是否真的是最好的:你可以通过递归在12位上有3个LCG
x_i(n)= a x_i(n-1)+ p_i(mod 2 ^ {12})
具有不同的素数p_i。如果a不是太大(比如说12位),这将永远不会溢出。然后,使用3个12位随机数,可以生成36位随机整数:
z(n)= x_0(n)+ 2 ^ {12} x_1(n)+ 2 ^ {24} x_2(n)
注意如果p_i是素数并且相对较大,则3个随机生成器应该是非常独立的,因此策略应该非常好。
困难在于有一个很好的选择。
无论如何,在使用它之前,我想最好做一些测试。