xorShift128 +的最大值(或者我的实现有什么问题)

时间:2019-10-03 16:43:06

标签: javascript algorithm random

我正在读取随机数生成器,并调整了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);

1 个答案:

答案 0 :(得分:1)

在xorshift128 +中,xy应该是uint64_t。这导致该实现与实际的xorshift128 +之间存在许多差异:

  • 向右移位是算术移位,但应该是逻辑移位。我不知道那有多糟,但是绝对不一样。
  • 最后的加法应该是模块化的,但是这里是(浮点)双精度和。太糟糕了。
  • 没有128位状态。这使PRNG的强度降低,但检测起来并不容易。

最终的总和不是模块化的,导致结果不一致,并且其范围与比例因子所假定的范围不同:[-2 31 .. 2 31 -1](使用Number代替uint64_t的结果)在[-2 32 .. 2 32 < / sup> -2],并偏向较小数量的数字。这与两个公平的掷骰之和具有相同的效果。可以通过添加>>> 0来解决此问题,但是代码仍然无法实现xorshift128 +。

解决基本问题会有些痛苦,需要模拟64位整数运算。有一些库可以为您完成这项工作。