【问题标题】:When does Math.random() start repeating?Math.random() 什么时候开始重复?
【发布时间】:2019-03-30 19:38:45
【问题描述】:

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

【问题讨论】:

  • 这里可能会回答它:hackernoon.com/…
  • 您的代码的一个问题是 Math.random() 在当前时间播种,因此即使 / 当它最终找到重复项时,您的结果也无法重复。
  • 我的意思是......它旨在随机的,而不是看似随机数字的重复序列。我不希望它开始重复......除非我误解了什么......
  • 那你有一个 X Y 问题。使用 UUID 或始终递增的时钟值,当 Date().valueOf() 返回不同的值时重置。 UUID 有一个涉及“机器 ID”的方案,这是一个本地时间源,可以在很长一段时间内为您提供唯一值。
  • @RyanTheLeach - 我现在明白了。我没有仔细查看您的代码,并认为您正在寻找顺序重复,而不仅仅是任何一个重复值。令人印象深刻的是,它在一夜之间没有找到重复项,尽管到晚上结束时,我想知道单次检查需要多长时间才能遍历您在v 中记录的每个值——它可能已经显着减慢.. .

标签: javascript node.js random


【解决方案1】:

相关(在另一个网站上):Acceptable to rely on random ints being unique?

也极其相关:How many double numbers are there between 0.0 and 1.0?

在数学上,0 到 1 之间的实数是无限的。但是,Math.Random 只能生成有限数量的可能值(因为计算机只有有限数量的位来表示数字)。假设它可以生成N 可能的值。然后,通过Pigeonhole Principle,一旦您准确生成N + 1 值,就有100% 的机会获得至少一个重复值。

此时,Birthday Paradox 表明您应该会以惊人的速度开始看到重复项。根据这个“悖论”(这不是真正的悖论,只是违反直觉),给定一个只有 23 人的房间,其中两人生日相同的可能性超过 50%。

回到我们的示例,计算此值的经验法则(请参阅链接的 Wikipedia 文章)表明,一旦您生成大约 sqrt(N) 数字,Math.Random 的重复概率就会达到 50%。

从链接的 Stack Overflow 问题中,如果我们假设在 0 和 1 之间有 7,036,874,417,766 个数字,就像接受的答案所说的那样(请阅读链接的问题以更详细地解释其中有多少实际上 是),那么 sqrt(7036874417766) 刚刚超过 265.2 万,实际上并没有那么多。如果您每秒生成 10,000 个随机数,您将在大约 737 小时内达到 50% 的概率,也就是不到 31 天。不幸的是,即使每秒 10,000 次,也需要大约 195,468 小时(大约 22.3 年)才能达到 100% 的概率。

其他一些答案给出的数字要高得多,所以请自行选择。

【讨论】:

  • @avo 谢谢,很高兴我能帮上忙。
【解决方案2】:

它是特定于浏览器的:

https://www.ecma-international.org/ecma-262/6.0/#sec-math.random

20.2.2.27 Math.random() 返回一个带正号的 Number 值,大于等于 0 但小于 1,随机或伪选择 在该范围内随机分布近似均匀, 使用依赖于实现的算法或策略。这个功能 不接受任何参数。

为不同代码领域创建的每个 Math.random 函数必须 从连续调用中产生不同的值序列。

这里的要求只是具有均匀分布的伪随机。

这是来自 V8(Chrome 和 NodeJs 的 Javascript 引擎)的博客文章。

https://v8.dev/blog/math-random

他们说他们正在使用xorshift128+,其最大周期为2^128 -1

【讨论】:

  • 2^128 听起来更有可能
  • 有趣。那么假设像Math.random() + "_" + new Date().valueOf() 这样的东西会生成唯一的字符串(针对特定的上下文),直到它被停止,这是否安全?
  • 永远不能保证你不会连续得到 2 个重复的数字,关键是它是伪随机的。如果您需要唯一性,请避免随机。如果您仍想使用随机作为 ID 的一部分,请使用经过良好测试的架构,例如 UUID
  • 参见stackoverflow.com/questions/23164474/… 使用 UUID 是清楚的、明确的,并且有据可查的碰撞机会。自行滚动将产生大量维护成本。
猜你喜欢
  • 2016-01-06
  • 2016-12-01
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
相关资源
最近更新 更多