[关闭]
@Wangww0925 2020-03-06T11:08:37.000000Z 字数 1481 阅读 316

toFixed()四舍五入的奇怪之处

js


问题

今天遇到一个很奇怪的问题 25.005.toFixed(2) 正常情况下我们都认为是 25.01 但实际情况是 25.00, 下面讲述下这是为什么。

toFixed() 规则:

四舍六入五考虑,
五后非零就进一,
五后为零看奇偶,
五前为偶应舍去,
五前为奇要进一

PS:toFixed() 四舍五入的规则与数学中的规则不同,使用的是银行家舍入规则,银行家舍入:所谓银行家舍入法,其实质是一种四舍六入五取偶(又称四舍六入五留双)法

例子

  1. 四舍六入五考虑
  2. 25.024.toFixed(2); // "25.02", 小于5都舍弃
  3. 25.026.toFixed(2); // "25.03", 大于5都进一
  4. 五后非零就进一
  5. 25.0251.toFixed(2); // "25.03", 5后面不是0就进一为6,变成25.026
  6. 25.0250.toFixed(2); // "25.02", 5后面为0就舍弃
  7. 五后为零看五前奇偶
  8. 25.025.toFixed(2); // "25.02", 五前为偶应舍去
  9. 25.0250.toFixed(2); // "25.02", 五后为零但五前为偶应舍去
  10. 25.035.toFixed(2); // "25.04", 五前为奇要进一
  11. 25.0350.toFixed(2); // "25.04", 五后为零但五前为奇要进一

解决

显然这样的规则不符合我们平常的数据处理,那么我们要怎样解决这个问题呢,我们知道Math.round()是四舍五入至整数,那么我们可以这样操作 Math.round(25.005 * 100) / 100 得到的是 25.01

将解决方法用原型封装

  1. /**
  2. * 自定义数值转成指定小数位数
  3. * num 数值
  4. * digit 小数位数,默认2
  5. */
  6. function toDecimal(digit = 2){
  7. var num = this
  8. typeof num == "string" ? num = parseFloat(num) : ""; // this如果是字符串,则转成数字类型
  9. typeof digit == "string" ? digit = parseFloat(digit) : ""; // 参数digit如果是字符串,则转成数字类型
  10. // 如果为NaN抛出异常
  11. if(isNaN(num)) throw "传入 " + num + " 数值错误"
  12. // 判断小数位数
  13. var n = 1;
  14. if(digit){
  15. for(var i = 0; i < digit; i++){ n *= 10 }
  16. };
  17. // 数值进行四舍五入计算
  18. var fixNum = (Math.round(num * n) / n).toString();
  19. // 小数位数不足时,补全
  20. if (digit != 0 && fixNum.indexOf(".") == -1) {
  21. fixNum += ".";
  22. }
  23. while (digit != 0 && fixNum.split(".")[1].length < digit) {
  24. fixNum += "0";
  25. }
  26. return fixNum; // 此处不能返回 parseFloat(fixNum),返回 parseFloat(fixNum) 会将 2.00 变成 2.
  27. }
  28. Number.prototype.toFixed = toDecimal
  29. String.prototype.toFixed = toDecimal
  30. "100".toFixed(); // 100.00
  31. "100".toFixed(0); // 100
  32. "100.005".toFixed(); // 100.01

作者 wendy
2019 年 1月 10日


参考文献

JS处理数据四舍五入(tofixed与round的区别详解)

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注