Math.random()的精度问题

14

JavaScript的Math.random()函数的精度是什么?


1
没错,那就是我想说的。谢谢! - jpc826
4个回答

11

Math.random() 生成一个浮点数,保留16位小数,大于或等于零且小于1。


8
JavaScript浮点数是64位IEEE 754值,因此它不是完全16个小数位。 - Pointy
@volatile:如果你的精度不是10的幂次。 - Brian
@Pointy 这是正确的,我的回答不够精确。顶一下。 - krs1
你有这个精度的任何参考资料吗? - Fabian Jakobs

10

这与浏览器/JavaScript引擎有关。

最大可能精度为52位,因为Math.random返回一个双精度浮点数,介于0(含)和1(不含)之间。这个最大值对应着大约16个小数位,详见Sly1024的回答。

实际上,许多浏览器给出了更小的精度。目前似乎是这样的:

运行下面的代码片段几次,你会发现在Chrome和Safari中,后面的21位总是0。

console.log((Math.random() * Math.pow(2,53)).toString(2));


IE11:52个随机位,尽管上面的代码有时会给出像“111000000101010100010110011011110111000111010101110.1”这样的结果。 - Andrew Morton
Chrome似乎已经升级了它们的精度,我再也无法观察到21个连续的0位。 - Daniel Vestøl
Chrome(以及所有基于Blink的浏览器和基于V8的产品,例如Electron应用程序和Node.js)在2015年将Math.random()精度更新为128位。 - Xyz
@Xyz,我可以了解一下2015年从32位精度更改为128位精度的相关帖子或源代码更改吗? - sken130
@sken130,好的!补丁错误问题。不确定这是在哪些版本的Chrome和Safari中发布的。澄清:底层精度在2015年更改为64位。如上所述,64位IEEE 754浮点数(JavaScript使用)中只有52位是实际精度。其余部分是符号位和指数。尽管如此,底层精度已更新为64位。我想我把128位搞混了。 - Xyz

5
根据维基百科:双精度浮点格式,小数部分有52位。我们知道这个数字在0到1之间(我认为不包括1),因此指数为-1,这留下了52个随机位。
52个随机位给出了52位的精度,在十进制中约为:
52*log10(2) ~= 15.653559774527022151114422525674 digits.

1

Math.random() 在 Javascript 中返回一个浮点数,范围在 0..1 之间,以本机 Javascript 格式表示,这是一种 64 位 IEEE 754 双精度浮点格式。由于该格式使用 52 位用于实际精度,因此在现代 Javascript 实现中,您实际上仅限于 52 位精度。

在实际使用中(以 10 进制为基础),这通常大致相当于 15-16 位数字。但是,如果数字以零结尾,则小数位数也可能更少。

如果您正在使用非常古老的 Javascript 实现(Internet Explorer、2016 年的 Safari 或 2015 年的 Chrome 或某些较旧的 Node 版本),则 Math.random() 可能使用仅具有 32 位精度的算法,这意味着精度的最后 20 位将只是 0,这意味着您将获得显着较少的精度。

如果您想要更高的精度,可以使用 Crypto.getRandomValues(new BigUint64Array(1)),这将使用经过验证的 CSPRNG 算法为您提供 64 位真正的精度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接