JavaScript 四舍五入误差

3

我在处理数字舍入方面遇到了问题。

x = 0.175;
console.log(x.toFixed(2));
// RESULT: 0.17

x = 1.175;
console.log(x.toFixed(2));
// RESULT: 1.18

x = 2.175;
console.log(x.toFixed(2));
// RESULT: 2.17

为什么 (X!=1).175 没有四舍五入到 X.18 呢?

2
我总是得到带有 *.18 的东西。 - Nina Scholz
5
尝试使用toFixed(20),你就会明白为什么了。 - georg
1
JavaScript 在数字系统方面很烂。 - Mahi
1
可能是toFixed JavaScript函数给出奇怪的结果?的重复问题。 - Mahi
@NinaScholz 是的,IE 给出了 .18。每个浏览器都有自己的计算方式。 - Mahi
4个回答

1
问题在于0.175在二进制中是一个重复的小数(具体来说,在短前缀之后,它会稳定为一个重复的0011模式)。当用有限的浮点表示法表示时,这个重复模式会被截断。当你把整数部分从0改变为1再改变为2时,每次都会向整数部分添加一个额外的位,这会推出一个尾随位。取决于哪个比特值被推出,这可能会改变舍入值,从而影响可见结果。请注意,在2.175之后,下一次舍入行为的变化要等到8.175才会发生(在表示中又推出了两个低位比特)。

0

这就是背后的原因...

将无限多的实数压缩到有限数量的比特中需要进行近似表示。

虽然整数有无限多个,但在大多数程序中,整数计算的结果可以存储在32位中。

相比之下,对于任何固定数量的比特,大多数实数计算将产生无法使用那么多比特精确表示的量。因此,浮点计算的结果通常必须舍入以适应其有限表示。

x = 0.175;
console.log(x.toFixed(20));
// RESULT: 0.17

x = 1.175;
console.log(x.toFixed(20));
// RESULT: 1.18

x = 2.175;
console.log(x.toFixed(20));
// RESULT: 2.17

这个舍入误差是浮点计算的特征。

来源:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html


2
你什么都没解释清楚。 - j08691
@j08691 是的,但他展示了正在发生的事情。 - JLRishe
1
那些想要校对的人可以访问http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html。 - Mahi

0
JavaScript存在许多舍入问题,这是二进制机器试图在十进制数字系统中表示分数的结果。总会存在不准确性。有时候,5会向上舍入,而其他时候则会向下舍入。这些文章或主题中都有讨论到这个问题:

http://www.jacklmoore.com/notes/rounding-in-javascript/

避免JavaScript中奇怪的小数计算问题

如何处理JavaScript中的浮点数精度?

即使在JavaScript中更精确地控制浮点表示,也无法解决这个问题:

> x=2175e-3; x.toFixed(2);
  "2.17"
> x=1175e-3; x.toFixed(2);
  "1.18"

在需要获得可预测结果的情况下,至少有一篇文章建议使用“epsilon估计”技术,这实际上是微积分中几个定义的核心。学习这个修复方法可能会让你学到更多的东西。

-3
JavaScript的数字始终是64位浮点数。
与许多其他编程语言不同,JavaScript没有定义不同类型的数字,如整数、短整型、长整型、浮点数等。
JavaScript的数字始终以双精度浮点数的形式存储,遵循国际IEEE 754标准。
最大小数位数为17,但浮点数运算并不总是100%准确。

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