JavaScript的Math.random的随机性如何?

6年来,我的网站上有一个随机数字生成器页面。 很长一段时间,这是谷歌“随机数字生成器”的第一个或第二个结果,并已被用来决定几十个,即使不是数百个讨论论坛和博客上的比赛和图纸(我知道,因为我看到在我的推荐人networking日志,通常去看看)。

今天有人给我发邮件告诉我可能不像我想象的那样随意。 她尝试生成非常大的随机数(例如,1到10000000000000000000),发现它们几乎总是相同的数字位数。 事实上,我把这个函数封装在一个循环中,所以我可以生成数以千计的数字,对于非常大的数字, 变化只有2个数量级。

为什么?

这里是循环版本,所以你可以自己尝试一下:

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

它包含了一个从Mozilla开发者networking中直接获得的实现,以及一些1997年的代码,我刷掉了一个不再存在的网页(Paul Houle的“Central Randomizer 1.3”)。 查看源代码,了解每种方法的工作原理。

我在这里和其他地方阅读了梅森·费尔斯特。 我感兴趣的是为什么JavaScript内置的Math.random函数的结果不会有更大的变化。 谢谢!

给定1到100之间的数字。

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

给定1到1000之间的数字。

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

等等。

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

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

有不同types的随机性。 Math.random给你一个统一的数字分布。

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

number = Math.floor(Math.exp(Math.random()*Math.log(maxmimum-minimum+1)))+minimum 

这行应该给你大致相同数目的2位数字和3位数字的1位数字。

还有一些随机数的分布,如正态分布(也称为高斯分布)。

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

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

看起来完全随机给我! (提示:依赖于浏览器)

就我个人而言,我认为我的实施会更好,虽然我把它从XKCD上偷了下来,谁都应该承认:

 random = 4; // Chosen by a fair dice throw. Guaranteed to be random. 

如果您使用像10000000000000000000这样的数字,那么您将超出Javascript正在使用的数据types的准确性。 请注意,所有生成的数字都以“00”结尾。

我尝试了混沌游戏上的JS伪随机数生成器。

我的Sierpiński三angular形说它非常随机: 分形

那么,如果你生成的数字是1e6,那么你将希望以大致相等的概率得到所有的数字。 这也意味着你只有十分之一的机会得到一个数字less一个数字。 百分之一获得两位数的机会,等等。我怀疑你使用另一个RNG时会看到很大的差别,因为你在数字上有一个统一的分布,而不是对数。