JavaScriptMath.random()
函数返回一个 0 到 1 之间的随机值,根据当前时间自动播种(类似于我相信的 Java)。但是,我认为没有任何方法可以为您设置种子。
我如何制作一个随机数生成器,我可以为其提供我自己的种子值,以便我可以让它产生一个可重复的(伪)随机数序列?
JavaScriptMath.random()
函数返回一个 0 到 1 之间的随机值,根据当前时间自动播种(类似于我相信的 Java)。但是,我认为没有任何方法可以为您设置种子。
我如何制作一个随机数生成器,我可以为其提供我自己的种子值,以便我可以让它产生一个可重复的(伪)随机数序列?
一种选择是http://davidbau.com/seedrandom,它是一个基于 RC4 的可种子 Math.random() 替代品,具有很好的属性。
如果您不需要播种功能,只需使用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));
如果您希望能够指定种子,您只需要替换对getSeconds()
和的调用getMinutes()
。你可以传入一个 int 并使用它的一半 mod 60 作为秒值,另一半 mod 60 给你另一部分。
话虽如此,这种方法看起来很垃圾。进行适当的随机数生成非常困难。一个明显的问题是随机数种子是基于秒和分钟的。猜测种子并重新创建随机数流只需要尝试 3600 种不同的秒和分钟组合。这也意味着只有 3600 种不同的可能种子。这是可以纠正的,但我从一开始就怀疑这个 RNG。
如果您想使用更好的 RNG,请尝试使用Mersenne Twister。它是一个经过良好测试且相当强大的 RNG,具有巨大的轨道和出色的性能。
编辑:我真的应该是正确的,并将其称为伪随机数生成器或 PRNG。
“任何使用算术方法产生随机数的人都处于犯罪状态。”
---约翰·冯·诺依曼
我使用 Mersenne Twister 的 JavaScript 端口:https : //gist.github.com/300494 它允许您手动设置种子。此外,正如其他答案中提到的,Mersenne Twister 是一个非常好的 PRNG。
您列出的代码有点像Lehmer RNG。如果是这种情况,则2147483647
是最大的 32 位有符号整数,2147483647
是最大的 32 位素48271
数, 是用于生成数字的全周期乘数。
如果这是真的,您可以修改RandomNumberGenerator
以接收额外的参数seed
,然后设置this.seed
为seed
; 但是你必须小心确保种子会导致随机数的良好分布(莱默可能会很奇怪) - 但大多数种子会很好。