Math.random() 何时开始重复?

9

我在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);

2
这里可能会回答你的问题:https://hackernoon.com/how-does-javascripts-math-random-generate-random-numbers-ef0de6a20131 - dwjohnston
我的意思是...它旨在是随机的,而不是一系列看似随机的数字的重复序列。我不会期望它开始重复...除非我误解了什么... - Alexander Nied
请点击文章末尾的链接 https://rawgit.com/lordpoint/xorshift-sandbox-and-visualizer/master/index.html 查看该链接的实时版本。 - Ryan Leach
1
那么你有一个X Y问题。使用UUID或始终递增,当Date()。valueOf()返回不同值时重置的时钟值。 UUID具有涉及“机器ID”的方案,本地时间源可以为您提供非常长时间的唯一值。 - Ryan Leach
1
@RyanTheLeach - 我现在明白了。我没有仔细审查你的代码,认为你正在寻找连续重复,而不是任何一个重复值。令人印象深刻的是,在没有找到重复项的情况下,它在一夜之间完成了,尽管到晚上结束时,如果要迭代记录在v中的每个值,单个检查需要多长时间可能会显著减慢... - Alexander Nied
显示剩余3条评论
2个回答

7

这是与浏览器相关的:

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


2
"2^128"听起来更有可能。 - Mat
有趣。那么可以安全地假设像 Math.random() + "_" + new Date().valueOf() 这样的东西会生成唯一字符串(对于特定上下文),直到它停止吗? - avo
4
不能保证不会出现连续重复数字,因为它是伪随机的。如果你需要独特性,请避免使用随机数。如果你仍想在ID中使用随机数,请使用经过充分测试的模式,如UUID。 - Ryan Leach
2
使用UUID是清晰、明确且有良好文档支持的,它们的碰撞概率已经被证实。自己编写将会有显著的维护成本。请参考https://stackoverflow.com/questions/23164474/how-unique-and-random-are-javascript-generated-uuids。 - Ryan Leach

4

相关(在另一个网站上):依赖于随机整数的唯一性是否可接受?

同样非常相关: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是可能值的数量)。

@avo 谢谢,很高兴能帮到你。 - EJoshuaS - Stand with Ukraine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接