JavaScript 的 Math.Random 有多随机?

6年来,我的网站上有一个 随机数发生器随机数发生器页面。很长一段时间以来,这是谷歌上第一个或第二个关于“随机数生成器”的搜索结果,并且已经被用来在论坛和博客上决定几十个甚至几百个比赛和图画(我知道这些是因为我在我的网络日志中看到了引用者,并且通常会去看一看)。

今天,有人给我发邮件告诉我 也许不像我想的那么随机。。她尝试生成非常大的随机数(例如,在1到1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000。实际上,我将函数封装在一个循环中,这样就可以生成数千个数字,而且对于非常大的数字,确实可以生成 变化只有两个数量级。

为什么?

Here is the looping version, so you can try it out for yourself:

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

它包括一个简单的实现,从 Mozilla Developer Network和一些代码,从1997年,我从一个不再存在的网页(保罗豪尔的“中央随机化1.3”)。查看源代码以查看每个方法的工作原理。

I've read 给你 and 其他地方 about 梅森旋转算法 What I'm interested in is why there wouldn't be greater variation in the results from JavaScript's built-in Math.random function. Thanks!

66841 次浏览

Looks perfectly random to me! (Hint: It's browser dependent.)

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

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

你的结果已经在预料之中了。如果随机数均匀地分布在1到10 ^ n 的范围内,那么你可以预期大约9/10的数字有 n 个数字,还有9/100的数字有 n-1个数字。

If you use a number like 10000000000000000000 you're going beyond the accuracy of the datatype Javascript is using. Note that all the numbers generated end in "00".

给出1到100之间的数字。

  • 9有1个数字(1-9)
  • 90有两个数字(10-99)
  • 1 has 3 digits (100)

给出1到1000之间的数字。

  • 9有1个数字
  • 90有两个数字
  • 900 have 3 digits
  • 1有4个数字

诸如此类。

所以如果你随机选择一些,那么绝大多数选中的数字都会有相同的位数,因为绝大多数可能的值都有相同的位数。

Well, if you are generating numbers up to, say, 1e6, you will hopefully get all numbers with approximately equal probability. That also means that you only have a one in ten chance of getting a number with one digit less. A one in a hundred chance of getting two digits less, etc. I doubt you will see much difference when using another RNG, because you have a uniform distribution across the numbers, not their logarithm.

有不同类型的随机性。 数学,随机给你一个统一的数字分布。

If you want different orders of magnitude, I would suggest using an exponential function to create what's called a 幂律分布幂律分布:

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

This function should give you roughly the same number of 1-digit numbers as 2-digit numbers and as 3-digit numbers.

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

下面的文章解释了主流 Web 浏览器中 math.Random ()是如何(不)安全的: ”主要浏览器和跨域信息中的临时用户跟踪 漏洞和攻击”,作者: Amid Klein (2008) ,它并不比典型的 Java 或 Windows 内置的 PRNG 函数强大

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

我在 abc0上试了 JS 伪随机数生成器。

我的 Sierpi 滑雪三角数据显示,这个数字相当随机: Fractal

从1到 N 均匀分布的非随机数具有相同的性质。请注意(在某种意义上)这是一个精度问题。在0-99(以整数形式)上的统一分布确实有90% 的数字是两位数。在0-999999上的统一分布有905个数字为五位数。

任何一组数字(在一些不太严格的条件下)都有一个密度。当有人想讨论“随机”数时,应该指定这些数的密度(如上所述)一个共同的密度是均匀的密度。还有其他的: 指数密度,正常密度,等等。在提出一个随机数生成器之前,必须选择哪个密度是相关的。此外,来自一个密度的数字往往可以很容易地通过各种手段转换成另一个密度。