6年来,我的网站上有一个random number generator页面。很长一段时间,它是Google上“随机数生成器”的第一个或第二个结果,并且已被用于在论坛和博客上决定数十个(如果不是数百个)竞赛和绘图(我知道因为我看到了我的推荐人)网络日志,通常去看看。
今天,有人通过电子邮件告诉我它可能不像我想的那么随意。她尝试生成非常大的随机数(例如,1到10000000000000000000之间)并发现它们几乎总是相同的位数。实际上,我将函数包装在一个循环中,因此我可以生成数千个数字,当然,对于非常大的数字,变化只有大约2个数量级。
为什么?
以下是循环版本,因此您可以自己试用:
http://andrew.hedges.name/experiments/random/randomness.html
它包括从Mozilla Developer Network和1997年的一些代码中直接执行的一些代码,我从不再存在的网页中删除了(Paul Houle的“Central Randomizer 1.3”)。查看源代码以了解每种方法的工作原理。
我已经阅读了关于 Mersenne Twister的here和elsewhere。我感兴趣的是为什么JavaScript内置的结果不会有更大的变化-in Math.random 函数。谢谢!
答案 0 :(得分:169)
给出1到100之间的数字。
给出1到1000之间的数字。
等等。
因此,如果您随机选择一些,那么绝大多数所选数字将具有相同的位数,因为绝大多数可能的值具有相同的位数。
答案 1 :(得分:55)
您的结果实际上是预期的。如果随机数均匀分布在1到10 ^ n的范围内,那么你可以预期大约有9/10的数字有n个数字,另外9/100有n到1个数字。
答案 2 :(得分:42)
有不同类型的随机性。 Math.random为您提供统一的数字分布。
如果您想要不同的数量级,我建议使用指数函数来创建所谓的power law distribution:
function random_powerlaw(mini, maxi) {
return Math.ceil(Math.exp(Math.random()*(Math.log(maxi)-Math.log(mini)))*mini)
}
此功能应该为您提供与2位数字和3位数字大致相同的1位数字数字。
还有其他随机数的分布,如normal distribution(也称为高斯分布)。
答案 3 :(得分:18)
以下文章解释了主要Web浏览器中的math.random()是如何(不)安全的: "Temporary user tracking in major browsers and Cross-domain information leakage and attacks" by Amid Klein (2008)。它并不比典型的Java或Windows内置PRNG功能更强大。
另一方面,实现时段2 ^ 19937-1的SFMT需要为每个PRNG序列维持2496字节的内部状态。有些人可能认为这是不可原谅的代价。
答案 4 :(得分:17)
对我来说完全随机! (提示:这取决于浏览器。)
就我个人而言,我认为我的实施会更好,尽管我从XKCD偷走了它,应该始终承认:
function random() {
return 4; // Chosen by a fair dice throw. Guaranteed to be random.
}
答案 5 :(得分:5)
如果使用10000000000000000000之类的数字,那么您将超出Javascript使用的数据类型的准确性。请注意,生成的所有数字都以“00”结尾。
答案 6 :(得分:5)
我在Chaos Game上尝试了JS伪随机数生成器。
我的Sierpiński triangle说它非常随机:
答案 7 :(得分:3)
好吧,如果您生成的数字高达1e6,那么您希望所有数字的概率几乎相等。这也意味着你只有十分之一的机会得到一个数字少一个数字。减少两位数的百分之一,等等。我怀疑你在使用另一个RNG时会看到很多不同,因为你在数字上有一个统一的分布,而不是它们的对数。
答案 8 :(得分:0)
从1到N均匀分布的非随机数具有相同的属性。请注意(在某种意义上)这是一个精确的问题。 0-99(作为整数)的均匀分布确实有90%的数字具有两位数。在0-999999上的均匀分布有905个数字有五位数。
任何一组数字(在一些不太严格的条件下)都有密度。当有人想讨论“随机”数字时,应指定这些数字的密度(如上所述)。常见密度是均匀密度。还有其他:指数密度,正常密度等。在提出随机数发生器之前,必须选择哪个密度是相关的。此外,来自一个密度的数字通常可以通过狡猾的手段轻易转换为另一个密度。