为什么谷歌Chrome;s Math.random数字生成器不是随机的
Why is Google Chrome's Math.random number generator not *that* random?
我今天在各种浏览器中运行一些单元测试时遇到了一个奇怪的"bug"。在今天之前,我已经在Firefox中运行了很多次测试,甚至在IE中也运行过,但显然还没有在Chrome(v19dev)中运行。当我在Chrome中运行它们时,它一直没有通过一次测试,因为我计算的两个值不匹配。
当我真正深入了解发生了什么时,我意识到问题是我假设如果我用100000个Math.random()
值填充一个数组,它们都是唯一的(不会有任何冲突)。在Chrome中发现这不是真的。
在Chrome中,我一直得到至少两对的值,这些值在100000中匹配。Firefox和IE9从未发生过冲突。下面是我为测试这一点而写的一个jsfiddle,它在数组中创建了1M个Math.random()
条目:http://jsfiddle.net/pseudosavant/bcduj/
有人知道为什么用于Math.random
的Chrome伪随机数生成器真的不是随机的吗?这似乎对任何使用Math.random
的客户端js加密例程都有影响。
显然,V8中的Math.random()只适用于32位值(过去甚至没有正确地随机化所有这些值)。使用32位,碰撞的概率在2^16=65k值左右达到50%。。。
其他答案已经解释了这个问题。如果你想在JavaScript中生成更好的伪随机数,我推荐这个页面作为一个好的起点:
http://baagoe.com/en/RandomMusings/javascript/
我将这个页面上的一个算法用于在浏览器中生成UUID的脚本,并且在测试中没有发生冲突。
2013年10月22日更新
链接到上面的页面不再有效。以下是Wayback Machine的快照链接:
http://web.archive.org/web/20120502223108/http://baagoe.com/en/RandomMusings/javascript/
这里有一个指向Node.js模块的链接,其中包括Alea.js:
https://npmjs.org/package/alea
请参阅https://medium.com/@betable/tifu-by-using-math-random-f1c308c4fd9d:
如果我们独立分析第一个子生成器,我们会发现它有32位内部状态。它不是全循环发电机—其实际循环长度约为5.9亿(18030*2⁵-1,数学很难,但这里和这里都有解释,或者你可以相信我)。因此,使用此生成器,我们最多只能生成5.9亿个不同的请求标识符。如果它们是随机选择的,那么在仅生成30000个标识符后,碰撞的几率将50%。
- 显示数字,然后每5秒随机更改一次(javascript)
- Javascript-如何从长度有时不是静态的随机字符串中获得3位数字
- 如果随机数字是3-Javascript的倍数,则将表单元格更改为红色
- 生成一个随机数字序列,然后用JavaScript在该序列后面附加一个大写字母
- 将随机整数分配给数组中的项,summa应该是一个固定的数字
- 如何将52个随机生成的数字打印到控制台
- 如何从自动填充随机数字的下拉菜单中生成一组文本框
- 从1-9之间的随机数字列表中选出3个相同的数字
- 如果语句是假的 JavaScript,则再次随机化数字
- 在节点中生成随机 32 位数字
- 使用 php(?) 在每个服务器日随机增加数字值
- 数字游戏 - 随机化
- Javascript - 如何使按钮生成 1-12 的随机整数,并让按钮不断产生相同的数字
- JavaScript 中的随机字母数字字符串
- 将每个选定的值替换为随机字母/数字
- 如何在任意范围内随机选择数字并使用 JavaScript 数组相加
- 创建一个中间带有随机数字的球(html画布和javascript)
- 使用setinterval在最终数字前显示随机数字
- 如何在有条件的JavaScript中生成随机数字序列
- POST随机数字段在客户端onsubmit生成