原创

关于JS四舍五入的探究

事情起因:近期在工作过程中,有需求需要在前端对一系列计算结果进行四舍五入运算,然而根据以往经验,直接使用了 toFixed() 方法直接处理。后经测试,并不是我们日常所理解的“四舍五入”

网上有些文章说 toFixed 使用的是 [银行家舍入],其实并不准确,不过这里也学习对比一下(https://baike.baidu.com/item/%E9%93%B6%E8%A1%8C%E5%AE%B6%E8%88%8D%E5%85%A5/4781630?fr=aladdin “银行家舍入”)

简单的说,就是:四舍六入五考虑,五后非空就进一,五后为空看奇偶,五前为偶应舍去,五前为奇要进一

但是实际应用中发现,其实并不是这样的, 像W3Cschool文档说明就是不准确的了 w3school toFixed() 方法

下图是使用 lodash.round() 方法与toFixed() 方法做的对比,可以发现 toFixed()的计算结果既不是我们日常理解的四舍五入,也不是上文说的银行家舍入,如:

入参 判断 期望结果 实际结果 是否符合银行家舍入
78.835 5后为空,5前为奇应进一 78.84 78.83 不符合
78.845 5后为空,5前为偶应舍去 78.84 78.84 符合

开始打算自己写一个四舍五入方法来处理,思路很简单

一个数乘以 10的X次方(X为要保留的小数位),然后使用Math.round()四舍五入取整,然后结果再除以10的X次方(X为要保留的小数位)

function myRound(val,decimal = 0) {
  const multiple = Math.pow(10, decimal);
  return Math.round(val * multiple) / multiple;
}
console.log(myRound(78.835,2));

然后发现结果还是不对,其实这个问题的根本原因还是因为JS浮点类型精度问题
经典js问题: 详解js中0.1+0.2!=0.3

console.log(78.835 * 100);  // 输出 7883.499999999999
// 此时再使用 Math.round() 得到的只能是 7883

如图上图发现,使用 lodash.round() 方法 ,是可以达到我们日常理解的四舍五入效果的,故查阅一下 Lodash 的源码 Lodash round(),发现其是使用科学计数法的方法来该表小数点的位置的,这样的好处就是不会造成失精问题。

console.log(Number("78.835e2")); // 输出 7883.5
// 此时再使用 Math.round() 得到的就是 7884

如此便能正确的四舍五入了。

类似文章

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注