是否有可能在JavaScript中播种随机数生成器(Math.random) ?


当前回答

对于0到100之间的数。

Number.parseInt(Math.floor(Math.random() * 100))

其他回答

请看Pierre L'Ecuyer在20世纪80年代末和90年代初的作品。还有其他的。如果你不是专家,自己创建一个(伪)随机数生成器是相当危险的,因为结果很可能不是统计随机的,或者有一个很小的周期。Pierre(和其他人)组合了一些很容易实现的(伪)随机数生成器。我用的是他的LFSR发电机。

https://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf

不,就像他们说的,不可能播种Math.random() 但你可以安装外部包,为这做准备。我使用这些包,可以安装使用这些命令

npm i random-seed

该示例来自包文档。

var seed = 'Hello World',
rand1 = require('random-seed').create(seed),
rand2 = require('random-seed').create(seed);
console.log(rand1(100), rand2(100));

点击链接获取文档https://www.npmjs.com/package/random-seed

不可能在Math中植入种子。随机函数,但是用Javascript实现一个高质量的RNG是可能的,只需很少的代码。

Javascript数字是64位浮点精度,可以表示小于2^53的所有正整数。这给我们的算法带来了一个硬限制,但在这些限制内,您仍然可以为高质量的Lehmer / LCG随机数生成器选择参数。

function RNG(seed) {
    var m = 2**35 - 31
    var a = 185852
    var s = seed % m
    return function () {
        return (s = s * a % m) / m
    }
}

Math.random = RNG(Date.now())

如果你想要更高质量的随机数,代价是速度慢10倍,你可以使用BigInt进行算术,并选择m刚好适合双精度的参数。

function RNG(seed) {
    var m_as_number = 2**53 - 111
    var m = 2n**53n - 111n
    var a = 5667072534355537n
    var s = BigInt(seed) % m
    return function () {
        return Number(s = s * a % m) / m_as_number
    }
}

参见Pierre l’ecuyer的这篇论文,了解上述实现中使用的参数: https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-00996-5/S0025-5718-99-00996-5.pdf

无论你做什么,避免使用Math.sin的所有其他答案!

不,不可能为Math.random()提供种子,但是编写自己的生成器相当容易,或者更好的是使用现有的生成器。

请看:这个相关的问题。

另外,请参阅David Bau的博客了解更多关于播种的信息。

Antti Sykäri的算法很好,很短。我最初做了一个变种来取代JavaScript的Math。当你调用Math.seed(s)时是随机的,但随后Jason评论说返回函数会更好:

Math.seed = function(s) {
    return function() {
        s = Math.sin(s) * 10000; return s - Math.floor(s);
    };
};

// usage:
var random1 = Math.seed(42);
var random2 = Math.seed(random1());
Math.random = Math.seed(random2());

这为您提供了JavaScript没有的另一个功能:多个独立的随机生成器。如果您希望同时运行多个可重复的模拟,这一点尤其重要。