为什么在JS中会截断 5726718050568503296

9

根据标准, ES将数字实现为IEEE754双精度浮点数。

而根据https://www.binaryconvert.com/result_double.html?decimal=053055050054055049056048053048053054056053048051050057054和其他编程语言的https://play.golang.org/p/5QyT7iPHNim显示,5726718050568503296值可以精确表示而不失去精度。

为什么在JS中会丢失3个有效数字(在最新稳定版的Google Chrome和Firefox中重现)?

这个问题最初是由在Golang中复制JavaScript不安全的数字触发的。

该值在双精度IEEE754中肯定是可表示的,看看Go语言中如何将裸位转换为float64:https://play.golang.org/p/zMspidoIh2w

2
IEEE 754双精度浮点数具有51位的尾数。大约相当于17个十进制数字。您的数字有19个数字。 - Barmar
4
顺便提一句,5726718050568503296 / 0b10011110111100101100011101110011011110011110100 正好等于 65536,也就是说 2**16。这个字符串表示方法有误吗?我的意思是,浮点数是正确的,但十进制字符串不正确。 - ASDFGerte
2
哎呀,我觉得我太累了,我不确定我是否犯了一些非常愚蠢的错误。无论如何,将数字写入一个类型化数组,并查看位,它是完全正确的。 - ASDFGerte
3
确实如此,JavaScript 可以正确地表示它,但默认的 toString 方法会产生错误的十进制数。 - ASDFGerte
2
我也开始阅读规范的那部分了,但说实话,我现在可能只能停下来了。这里已经是凌晨3点了,我非常疲惫。我现在无法撰写完整的答案,因为需要时间来确定规范是否允许这样做(很可能是),或者是否还有其他问题。也许有人知道,并且会写一个答案,那么在我好好休息一晚后我就可以愉快地阅读它了。 - ASDFGerte
显示剩余57条评论
1个回答

13

JavaScript在将Number值转换为十进制数时的默认规则是使用足够数量的数字来区分该Number值。具体而言,这源自于ECMAScript 2017语言规范第7.1.12.1条款中的第5步,根据链接的回答可知。(在2020版中是6.1.6.1.20)。

因此,虽然5,726,718,050,568,503,296是可表示的,但打印出来的结果是“5726718050568503000”,因为这已足以将其与相邻的可表示值5,726,718,050,568,502,272和5,726,718,050,568,504,320区分开来。

您可以通过使用.toPrecision来请求更多精度,例如x.toPrecision(21)


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