可播种的 JavaScript 随机数生成器
2022-08-30 01:47:14
JavaScript Math.random()
函数返回一个介于 0 和 1 之间的随机值,根据当前时间自动设定种子(我相信类似于 Java)。但是,我不认为有任何方法可以为它设定自己的种子。
如何制作一个随机数生成器,我可以为其提供自己的种子值,以便我可以让它产生可重复的(伪)随机数序列?
JavaScript Math.random()
函数返回一个介于 0 和 1 之间的随机值,根据当前时间自动设定种子(我相信类似于 Java)。但是,我不认为有任何方法可以为它设定自己的种子。
如何制作一个随机数生成器,我可以为其提供自己的种子值,以便我可以让它产生可重复的(伪)随机数序列?
如果您不需要种子设定功能,只需使用它并围绕它构建帮助程序函数(例如)。Math.random()
randRange(start, end)
我不确定您正在使用什么RNG,但最好了解并记录它,以便您了解其特征和局限性。
就像Starkii说的,Mersenne Twister是一个很好的PRNG,但它并不容易实现。如果你想自己做,试着实现一个LCG - 它非常简单,具有不错的随机性质量(不如Mersenne Twister好),你可以使用一些流行的常量。
编辑:考虑这个答案中简短的可种子RNG实现的绝佳选项,包括LCG选项。
function RNG(seed) {
// LCG using GCC's constants
this.m = 0x80000000; // 2**31;
this.a = 1103515245;
this.c = 12345;
this.state = seed ? seed : Math.floor(Math.random() * (this.m - 1));
}
RNG.prototype.nextInt = function() {
this.state = (this.a * this.state + this.c) % this.m;
return this.state;
}
RNG.prototype.nextFloat = function() {
// returns in range [0,1]
return this.nextInt() / (this.m - 1);
}
RNG.prototype.nextRange = function(start, end) {
// returns in range [start, end): including start, excluding end
// can't modulu nextInt because of weak randomness in lower bits
var rangeSize = end - start;
var randomUnder1 = this.nextInt() / this.m;
return start + Math.floor(randomUnder1 * rangeSize);
}
RNG.prototype.choice = function(array) {
return array[this.nextRange(0, array.length)];
}
var rng = new RNG(20);
for (var i = 0; i < 10; i++)
console.log(rng.nextRange(10, 50));
var digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
for (var i = 0; i < 10; i++)
console.log(rng.choice(digits));