JavaScript 的 Math.random 有多随机?

IT技术 javascript random
2021-02-02 16:27:36

6 年来,我的网站上有一个随机数生成器页面。很长一段时间以来,它是 Google 上“随机数生成器”的第一个或第二个结果,并且已被用来决定讨论论坛和博客上的数十个甚至数百个竞赛和绘图(我知道,因为我在我的网络日志,通常去看看)。

今天,有人给我发了电子邮件,告诉我这可能不像我想象的那么随意。她尝试生成非常大的随机数(例如,介于 1 和 10000000000000000000 之间)并发现它们几乎总是相同的位数。确实,我将函数包装在一个循环中,这样我就可以生成数千个数字,果然,对于非常大的数字,变化只有大约 2 个数量级。

为什么?

这是循环版本,因此您可以自己尝试一下:

http://andrew.hedges.name/experiments/random/randomness.html

它包括从Mozilla 开发人员网络获取的直接实现和 1997 年我从不再存在的网页上刷下的一些代码(Paul Houle 的“Central Randomizer 1.3”)。查看源代码以了解每种方法的工作原理。

我在这里其他地方都读过关于Mersenne Twister 的文章。我感兴趣的是为什么 JavaScript 的内置Math.random函数的结果不会有更大的变化谢谢!

6个回答

给定 1 到 100 之间的数字。

  • 9 有 1 个数字 (1-9)
  • 90 有 2 位数字 (10-99)
  • 1 有 3 位数字 (100)

给定 1 到 1000 之间的数字。

  • 9 有 1 个数字
  • 90有2位数
  • 900 有 3 个数字
  • 1 有 4 位数字

等等。

因此,如果您随机选择一些,那么绝大多数选定的数字将具有相同的位数,因为绝大多数可能的值具有相同的位数。

作为记录,我对这个和@jwoolard 的答案都投了赞成票。我选择这个作为公认的答案,因为这些例子清楚地说明了为什么数字的分布偏向于具有更多位数的数字。
2021-03-21 16:27:36
你对随机性意味着完美和均匀分布的想法很有趣......
2021-03-22 16:27:36
再读一遍。@David 只是说明限制之间有什么样的数字,而不是选择 N 个随机数的结果。我承认标题有误导性。
2021-03-23 16:27:36
@andrew-hedges 说得对——这是更清楚的答案,但谢谢:)
2021-04-01 16:27:36
@R.Pate - 随机数生成没有多大用处,除非它在长期范围内均匀分布
2021-04-12 16:27:36

您的结果实际上是预期的。如果随机数均匀分布在 1 到 10^n 的范围内,那么您会期望大约 9/10 的数字具有 n 位数字,另外 9/100 具有 n-1 位数字。

确切地。预计位数的分布会出现偏差。然而,位数的对数分布应该是均匀的。
2021-04-06 16:27:36

有不同类型的随机性。Math.random为您提供均匀分布的数字。

如果您想要不同的数量级,我建议使用指数函数来创建所谓的幂律分布

function random_powerlaw(mini, maxi) {
    return Math.ceil(Math.exp(Math.random()*(Math.log(maxi)-Math.log(mini)))*mini)
}

此函数应为您提供与 2 位数字和 3 位数字大致相同的 1 位数字数量。

还有其他随机数分布,如正态分布(也称为高斯分布)。

@shinzou 我在math.stackexchange 上,得到了一个稍微不同的公式作为答案。我更改了代码以反映来自 math.stackexchange 的数学推导公式。
2021-03-23 16:27:36
使用这个算法,我把minimum = 1maximum = 10,结果有时会得到 11。您可能打算使用Math.floor而不是Math.round
2021-04-06 16:27:36
为什么有效?它是否将均匀分布转换为指数分布?
2021-04-13 16:27:36

对我来说看起来完全随机!(提示:这取决于浏览器。)

就我个人而言,我认为我的实现会更好,尽管我从XKCD那里偷走了它,应该永远承认:

function random() {
  return 4; // Chosen by a fair dice throw. Guaranteed to be random.
}
+1 表示它依赖于浏览器,-1 表示借用 xkcd 而没有链接。
2021-03-25 16:27:36
无论是否需要,因为它是 xkcd,所以它得到了归因。:)
2021-03-31 16:27:36
OT:我很惊讶也很高兴“XKCD”是本周大学挑战问题的答案:D
2021-04-01 16:27:36
贝尔吉:直接链接还不够?
2021-04-05 16:27:36
我认为他们的意思是这个笑话没有被正确引用(“random = 4;”而不是“return 4;”)
2021-04-08 16:27:36

以下论文解释了主要 Web 浏览器中的 math.random() 如何是(不)安全的: Amid Klein (2008) 的“主要浏览器中的临时用户跟踪和跨域信息泄漏和攻击”它并不比典型的 Java 或 Windows 内置 PRNG 函数强。

另一方面,实现 2^19937-1 周期的 SFMT 需要为每个 PRNG 序列维护 2496 字节的内部状态。有些人可能认为这是不可原谅的成本。

+1:提到的论文很棒,远远超出了最初的问题。
2021-04-07 16:27:36