我在nodejs中有一个简单的测试,我让它在过夜,但无法使Math.random()重复。我意识到更早或更晚这些值(甚至整个序列)将会重复,但是否有可以预期的合理时间?
let v = {};
for (let i = 0;; i++) {
let r = Math.random();
if (r in v) break;
v[r] = r;
}
console.log(i);
我在nodejs中有一个简单的测试,我让它在过夜,但无法使Math.random()重复。我意识到更早或更晚这些值(甚至整个序列)将会重复,但是否有可以预期的合理时间?
let v = {};
for (let i = 0;; i++) {
let r = Math.random();
if (r in v) break;
v[r] = r;
}
console.log(i);
这是与浏览器相关的:
https://www.ecma-international.org/ecma-262/6.0/#sec-math.random
20.2.2.27 Math.random()返回一个数字值,带有正号,大于或等于0但小于1,通过使用实现依赖算法或策略随机或伪随机地选择该范围内具有近似均匀分布的值。此函数不需要参数。
为不同代码领域创建的每个Math.random函数必须从连续调用中产生不同的值序列。
这里的要求只是伪随机且均匀分布。
以下是来自V8(Chrome和NodeJs的Javascript引擎)的博客文章。
https://v8.dev/blog/math-random
他们说他们正在使用xorshift128+,其最大周期为2^128-1
。
Math.random() + "_" + new Date().valueOf()
这样的东西会生成唯一字符串(对于特定上下文),直到它停止吗? - avo相关(在另一个网站上):依赖于随机整数的唯一性是否可接受?
同样非常相关:0.0和1.0之间有多少个双精度数?
从数学上讲,在0和1之间有无限多个实数。然而,Math.Random
能够生成的可能值只有有限个(因为计算机只有有限的位数来表示数字)。假设它能够生成N
个可能值。那么,根据鸽巢原理,一旦你生成了恰好N + 1
个值,就有100%的概率至少会得到一个重复值。
在这一点上,生日悖论 表明你应该很快开始看到重复的情况。根据这个“悖论”(它并不是真正的悖论,只是违反直觉),在一个只有23个人的房间里,有超过50%的机会两个人拥有相同的生日。
回到我们的例子,计算这个问题的经验法则(请参阅链接的维基百科文章)建议,一旦生成了大约 sqrt(N)
个数字,Math.Random
就会达到50%的重复概率。
从链接的 Stack Overflow 问题中,如果我们假设在 0 到 1 之间有 7,036,874,417,766 个数字,就像被接受的回答所说的一样(请阅读链接的问题以获取关于实际上有多少数字的更详细说明),那么 sqrt(7036874417766) 稍微超过了 2.652 百万,这其实并不是很多。 如果您每秒生成 10,000 个随机数,那么您将在大约 737 小时内达到 50% 的概率,这相当于不到 31 天的时间。 不太幸运的是,即使每秒生成 10,000 个随机数,也需要大约 195,468 小时(约为 22.3 年)才能达到 100% 的概率。
其他答案给出了更高的数字,所以选择吧。
此外,要注意赌徒谬误 - 事实上,您刚刚生成一个值并不意味着同样的值不会再次出现。因此,无论您已经生成了多少次特定的值,下一个随机数是相同值的概率仍然是1/N
(其中N
是可能值的数量)。
v
中的每个值,单个检查需要多长时间可能会显著减慢... - Alexander Nied