提问人:Li Haoyi 提问时间:9/14/2023 更新时间:9/17/2023 访问量:79
为什么 Javascript 的 'parseFloat' 在截断超大数字时返回的值与 Java 的 'java.lang.Double.parseDouble' 不同?
Why does Javascript's `parseFloat` return a different value than Java's `java.lang.Double.parseDouble` when truncating over-sized numbers?
问:
Javascript的:
> parseFloat("738529527931269425")
738529527931269400
爪哇岛:
@ java.lang.Double.parseDouble("738529527931269425")
res4: Double = 7.3852952793126938E17
@ (long)java.lang.Double.parseDouble("738529527931269425")
res5: Long = 738529527931269376L
它们不应该是一样的吗?其中一个错了吗?或者是否有多种有效的方法可以截断过于精确的十进制数以适应 64 位浮点数?
答:
1赞
Hoopje
9/17/2023
#1
事实上,结果是一样的。区别在于字符串表示形式,而不是实际存储在内存中的双精度值。
双精度数(在 Java 中)和数字(在 JavaScript 中)是 IEEE-754 标准指定的 64 位二进制浮点数。它们的精度为 53 位,大约是 15 位十进制数字。这些位/数字是在二进制/小数分隔符之前还是之后并不重要。您的数字有 18 位有效数字,因此并非其邻域中的所有整数都可以准确表示。因此,数字需要四舍五入到可以表示的最接近的数字。字符串“738529527931269376”、“7.3852952793126938E17”、“738529527931269400”和“738529527931269425”都映射到完全相同的双精度值,这是最接近它们的一个。例如:
Double.parseDouble("7.3852952793126938E17") == Double.parseDouble("738529527931269400")
// ==> true
将浮点值转换为字符串时,可以选择将映射回该浮点值的多个字符串中的任何一个。大多数编程语言不会简单地将浮点值的确切值输出为十进制字符串,而是在所有可能的字符串中选择“最简单”的字符串。当然,“简单”的定义不是很清楚,这就是你在这里看到不同结果的原因。
评论