Javascript中的四舍五入方法toFixed()

5

我知道javascript的toFixed()方法将数字转换为字符串,并保留指定数量的小数位,就像下面的代码一样,将小数点后的数字设置为2

我的问题是:当需要时,这个数字是否会被四舍五入。就像下面的代码中,我要把数字0.075转换成字符串。我认为四舍五入后的结果应该是0.08,因为“5进1”。然而,在第一个代码示例中看起来很奇怪,所以我感到困惑。

var a=0.25*0.3;
var res1 = a.toFixed(2);
console.log(res1);
//Output: a is 0.07 (Is there something wrong?)

var b=0.025*3;
var res2= b.toFixed(2);
console.log(res2);
//Output:b is 0.08

我知道这个问题可以通过使用Math.js来解决。但是,我想知道这个问题的原因是什么?是toFixed()方法的问题还是javascript中的数据类型的问题。


4
好的,第二个。尝试使用“.toFixed(22)”,你会明白为什么。 - georg
1
无法复现。 - Jonas Wilms
1
我假设第二个代码块应该有 var b=0.025*3; - radulfr
1
这对我来说看起来很奇怪 - 为什么 b.toFixed(2) 应该返回 0.08b = 0.0075 - Nico Haase
1
b.toFixed(2); is .08??? huh, I am not seeing that .0075 would be .01 - epascarello
显示剩余4条评论
2个回答

2
文档所述,toFixed()确实会在必要时进行四舍五入。其取整规则是,-.5 < x <= +.5 这个范围内的数字将被四舍五入到最接近的数位。
你观察到的奇怪行为与上面链接文档中的注释一致:

浮点数不能精确地表示所有二进制小数,这可能导致出现意外结果,例如 0.1 + 0.2 === 0.3 返回 false。

换句话说,这是浮点精度丢失的经典案例——你会在几乎任何语言中遇到这个问题。如果你观察ab的完整输出,你会发现由于浮点精度问题,a == 0.075b == 0.07500000000000001,因此根据定义的取整规则,将a取整到.07,将b取整到.08是合理的。

非常感谢。您能否解释一下toFixed()的舍入规则?因为我认为它不是银行家舍入,银行家舍入会将值四舍五入到最接近的偶数,否则,a==0.075=0.8。我还尝试打印toFixed(22),结果显示:a=0.0749999999999999972244 b=0.0750000000000000111022。这与这个奇怪的情况有关吗? - s666
就像我之前所写的那样,换句话说,小数部分直到0.5(包括0.5)被舍入到较低的整数,即使是最微小的超过0.5的小数也会被舍入到较高的整数。我不确定toFixed如何工作,但看起来你正在要求它显示比默认显示数量更高的精度,这揭示了许多有效数字的精度损失。从这个意义上讲,你可以清楚地看到a < 0.75和b > 0.75,这就是它们舍入方向不同的原因。 - Klaycon
是的,我明白了。我认为,就像你所说的,在计算机中并不总是“四舍五入”,这意味着有些情况下会出现这样的情况:0.555=0.55,1.555=1.56。 - s666

1
你遇到的问题不仅仅是JavaScript特有的,它在计算机中普遍存在。
这两个算术计算结果相同 - 0.075:
0.25 * 0.3 = 0.075 0.025 * 3 = 0.075
这是使用常见的十进制数系统。
然而,计算机的核心并不使用十进制系统,而是二进制 - 一切都基于0和1。
因此,它们实际上很难正确地进行上述计算。JavaScript和其他编程语言必须近似计算结果,给出以下结果:
0.25 * 0.3 = 0.75 0.025 * 3 = 0.07500000000000001
现在你可以看到为什么toFixed返回不同的结果:
0.75.toFixed(2) = 0.07 0.07500000000000001.toFixed(2) = 0.08

是的!但我在想为什么0.075.toFixed(2)= 0.07,是因为0.075实际上是0.7499999.....,而toFixed()使用“5进1”的方式进行四舍五入。 - s666
我认为这是因为四舍五入的规则是1-5向下取整,6-9向上取整,但我只能猜测,不是专家。 - Patrick Hund

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