JS 的 toFixed
javascript 数字处理 精度
银行家舍入法
toFixed 经常被用来保留指定位数的小数,我很长一段时间都认为其遵循四舍五入原则,实际上并不是,它遵循的实际上是”银行家舍入法”。
其实用一句话就可以概括:四舍六入五成双。
详细算法如下:
- 保留位数的后一位如果小于 5,则舍去。
- 保留位数的后一位如果大于 5,则进上去。
- 保留位数的后一位如果是 5
- 且 5 后面仍有数,则无论奇偶都要进入。
- 若 5 后面不再有数,要根据尾数“5”的前一位决定: 如果是奇数则进入,如果是偶数则舍去。
举个例子:(以保留两位小数为例)
5.214 ≈ 5.21(4小于5)
5.216 ≈ 为5.22(6大于5)
5.2254 ≈ 5.23(5后面有数,进入)
5.215 ≈ 5.22(5后面没数,前一位1是奇数,进入)
5.225 ≈ 5.22(5后面没数,前一位2是偶数,舍弃)
目前,大部分编程语言都是默认使用“奇进偶舍”,比如 C/C++、JavaScript、PHP、Go 等。
使用 JS 测试:
(5.214).toFixed(2);
("5.21");
(5.216).toFixed(2);
("5.22");
(5.2254).toFixed(2);
("5.23");
(5.215).toFixed(2);
("5.21");
(5.225).toFixed(2);
("5.22");
结果发现 5.215 并没有约等于 5.22,而是约等于 5.21。 这里其实是因为 浮点数精度问题导致的误差。
(5.215).toPrecision(17);
("5.2149999999999999");
5.215 底层是 5.214999……,那么此时按照奇进偶舍的规则,第三位 4 小于 5 直接舍弃,就成了 5.21。
看到一些说法是不同浏览器内核对 toFixed 的实现会有一些出入,这里仅作为个人记录。