JavaScript的Math.random有多随机?


116

六年来,我在网站上拥有一个随机数生成器页面。长期以来,它是Google在“随机数生成器”上的第一个或第二个结果,已被用于决定数十个(甚至数百个)讨论论坛和博客上的竞赛和绘图(我知道,因为我在我的网站上看到了引荐来源网络日志,通常可以去看看)。

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

为什么?

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

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

它既包含来自Mozilla开发人员网络的直接实现,也包含1997年的一些代码,这些代码我从一个不存在的网页上擦掉(Paul Houle的“中央随机化器1.3”)。查看源代码以了解每种方法的工作原理。

我读过这里其他地方的赛特旋转。我感兴趣的是,为什么JavaScript的内置Math.random函数的结果不会有更大的变化。谢谢!


“ sarnath'd”,被殴打,或者在这种情况下,是答案
maetl 2009年

5
如果你正在寻找的答案,在标题的问题,请参见stackoverflow.com/questions/2344312/...
安德鲁B.

Answers:


182

给定1到100之间的数字。

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

给定1到1000之间的数字。

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

等等。

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


11
您对随机性的理解意味着完美而均匀地分布,这很有趣……

19
@ R.Pate-随机数生成除非将其大规模地均匀分布,否则就没什么用了
annakata

3
再读一次。@David仅说明限制之间存在哪种数字,而不是选择N个随机数字的结果。我确实承认所有权具有误导性。
nikc.org 2009年

3
记录下来,我对这个和@jwoolard的答案都投了赞成票。我选择此答案作为可接受的答案,因为这些示例清楚地说明了为什么数字分布偏向于具有更多数字的数字。
Andrew Hedges,2009年

1
@ andrew-hedges非常正确-这是更清晰的答案,但谢谢:)
jwoolard

56

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


8
究竟。位数的分布预计将出现偏差。但是,位数的对数的分布应该是均匀的。
Noldorin

45

有不同类型的随机性。Math.random使您可以均匀分配数字。

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

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

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

对于随机数,还存在其他分布,例如正态分布(也称为高斯分布)。


使用此算法,我把minimum = 1maximum = 10和有时会得到11的结果。您可能打算Math.floor代替Math.round
Sam Eaton

1
为什么行得通?它将均匀分布转换为指数分布吗?
shinzou

@shinzou我在math.stackexchange询问并得到了一个略有不同的公式作为答案。我更改了代码以反映从math.stackexchange的数学派生公式。
基督徒

20

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

就个人而言,我认为我的实现会更好,尽管我从XKCD中偷走了它,但应该始终承认:

function random() {
  return 4; // Chosen by a fair dice throw. Guaranteed to be random.
}

19
+1表示依赖于浏览器,-1表示借用xkcd而不进行链接。

是否为必填项,因为它是xkcd,因此已被赋予属性。:)
Arafangion

2
OT:“ XKCD”是本周大学挑战赛的答案,我感到很惊讶和高兴:D
Matt Sach

2
Bergi:直接链接还不够吗?
Arafangion

我认为这表示该笑话没有被正确引用(“随机= 4;”而不是“返回4;”)
Eren Tantekin

18

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

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


1
+1:提到的论文很棒,远远超出了最初的问题。
罗兰·伊利格

6

如果使用10000000000000000000之类的数字,那么您将超出Javascript正在使用的数据类型的精度。注意,所有生成的数字都以“ 00”结尾。


1
不过,在这种情况下,这不是他的问题。
乔伊(Joey)

3
@
Johannes-

IEE754的分配不均。也许您可以以2的增量表示0到999,并且具有足够的精度,所以如果您多次选择数字,您会发现该范围内的分布均匀。10%将是两位数,而90%将是三位数。但是,当您开始达到非常高的数字时,增量将超过1。您可能只能从一万亿增加到一万亿,而不是一万亿。尽管对于少量/规模,这种影响将不存在。规模效应将产生更大的影响。
jgmjgm

5

我在Chaos Game上尝试了JS伪随机数生成器。

我的Sierpiński三角形说的很随机: 分形


2
您介意在此处和jsfiddle / jsbin中共享三角代码,以便我们可以轻松地在实践中针对不同的浏览器进行检查吗?
法布里西奥磨砂

1
好的,但是请给我几天时间,因为我需要将代码翻译成英语。现在是波兰语,我有很多工作。
zie1ony13年

1
@ zie1ony几天过去了。
trusktr 2013年

1
USP :(工作,工作,工作链路:kubaplas.vot.pl/green/fractal第一个参数是顶点的NR第二个是线段的交叉点(从0到1)的一个点仅有实验。
zie1ony

4
链接死了-也许是Github回购?
Mark K Cowan

3

好吧,如果您生成的数字最大为1e6,则希望所有数字的概率大致相等。这也意味着获得数字少一位的机会只有十分之一。有一百分之一的机会减少两位数,等等。我怀疑您在使用其他RNG时会看到很大的不同,因为您在数字上的分配是均匀的,而不是对数。


0

从1到N均匀分布的非随机数具有相同的属性。请注意(从某种意义上来说)这是一个精度问题。0-99(整数)上的均匀分布的确有90%的数字是两位数。0-999999上的均匀分布有905个数字,其中有五个数字。

任何一组数字(在某些不太严格的条件下)都具有密度。当有人想讨论“随机”数字时,应指定这些数字的密度(如上所述)。常见的密度是均匀密度。还有其他一些:指数密度,标准密度等。在提议随机数生成器之前,必须选择与哪种密度相关。同样,通常可以通过龋齿的方式将来自一种密度的数字轻松转换为另一种密度。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.