Javascript中的自定义线性同余生成器

时间:2013-07-12 22:58:18

标签: javascript canvas random functional-testing lcg

我正在尝试在Javacript中创建一个自定义线性同余生成器(glibc中使用的生成器)。
on wikipedia所述,其属性为:m=2^31a=1103515245c=12345

现在我用

获得下一个种子值
x = (1103515245 * x + 12345) % 0x80000000 ; // (the same as &0x7fffffff)

虽然生成器似乎可以工作,但是当在画布上测试数字时:

cx = (x & 0x3fffffff) % canvasWidth; // coordinate x (the same for cy)
他们似乎非常偏颇:http://jsfiddle.net/7VmR9/3/show/

有关为何会发生这种情况的任何想法?通过选择不同的模数,视觉测试的结果看起来更好。

测试jsfiddle在这里:http://jsfiddle.net/7VmR9/3/

更新

最后我将转换修改为画布坐标,如下式所示:

var cx = ((x & 0x3fffffff)/0x3fffffff*canvasWidth)|0

现在,像素坐标与使用模运算时的格式不同 更新了小提琴:http://jsfiddle.net/7VmR9/14/

2 个答案:

答案 0 :(得分:2)

对于生成器,公式为(您忘记了第一部分的模数):

current = (multiplier * current * modul + addend) % modulus) / modulus

我意识到你试图优化它,所以我更新了这个小提琴,所以你可以用它作为优化的基础:

http://jsfiddle.net/AbdiasSoftware/7VmR9/12/

答案 1 :(得分:2)

是的,看起来你解决了它。我做了同样的事情。

线性同余生成器的形式为:

seed = (seed * factor + offset) % range;

但是,最重要的是,当从中获取实际随机数时,以下不起作用:

random = seed % random_maximum;

这不起作用,因为第二模数似乎抵消了发电机的影响。相反,您需要使用:

random = floor (seed / range * random_maximum);

(这将是一个随机整数;删除floor调用以获得随机浮点数。)


最后,我会警告你:在javascript中,当处理超过dword限制的数字时,会有精度损失。因此,您的LCG的随机结果可能是随机的,但它们很可能与C ++中实现的相同LCG或实际支持双字数学的其他低级语言的结果不匹配。

同样由于不精确,LCG的循环很容易大大减少。因此,例如,你引用的glibc LCG的周期大概是40亿(也就是说,它会在重新开始并重新生成完全相同的数字集之前生成超过40亿个随机数)。这个js实现可能只有10亿,或者可能远远少于,因为当乘以因子时,数量超过40亿,并且这样做会失去精确度。