我正在读取随机数生成器,并调整了JavaScript中xorShift128 +算法的实现。尽管我仍在学习为什么它们有用,以及为什么在xorShift128 +中使用它们会产生均匀的随机分布,但我了解位移运算符如何工作以及异或运算是如何工作的。
但更重要的是,我只需要知道它可以处理的数字范围是多少。它输出整数,我试图获取0到1之间的数字。归纳地,我看到它的数量级为2 ** 32。因此,我将其用作除数。但是,当我检查一致性时,我发现数字有偏差。它们似乎在0.2 <= val <0.3和val> = 0.7的区域被排斥。
所以我要么校正因子错误,要么实现错误,要么就均匀性感到困惑。任何帮助,将不胜感激。以下是我的代码和分析:
function xorShift128p(seed) {
// seeds
this.x = seed || this.x || 1;
this.y = seed + 1 || this.y || 2;
// swap seeds
let x = this.y;
let y = this.x;
// bit manipulations that are still a little
// obscure to me as to why they work well
y ^= y << 23;
y ^= y >> 17;
y ^= x;
y ^= x >> 26;
// reset seeds
this.x = x;
this.y = y;
// output, with calibration for 0-1 range.
let realResult = x + y;
let myCalibration = realResult / (2**32);
return myCalibration;
}
// produce an array of 100 random numbers using xorShift128p
let rands =
[...new Array(100).keys()]
.map(() => xorShift128p());
// bin the random numbers into units of 0.1
let binCounts =
[...new Array(10).keys()]
.map(key =>
`lead: ${(key / 10).toFixed(1)}, ` +
`count: ${rands.filter(r => r >= key / 10 && r < (key + 1) / 10).length}`
);
// notice the non-uniformity
console.log(binCounts);
答案 0 :(得分:1)
在xorshift128 +中,x
和y
应该是uint64_t
。这导致该实现与实际的xorshift128 +之间存在许多差异:
最终的总和不是模块化的,导致结果不一致,并且其范围与比例因子所假定的范围不同:[-2 31 .. 2 31 -1](使用Number代替uint64_t
的结果)在[-2 32 .. 2 32 < / sup> -2],并偏向较小数量的数字。这与两个公平的掷骰之和具有相同的效果。可以通过添加>>> 0
来解决此问题,但是代码仍然无法实现xorshift128 +。
解决基本问题会有些痛苦,需要模拟64位整数运算。有一些库可以为您完成这项工作。