【四舍五入精度丢失】答应我,不要再使用toFixed了好吗?

293 阅读2分钟

toFixed语法:

var num = 5.56789;  
var n=num.toFixed(2);

toFixed可以将一个数字转为一个字符串,并且保留指定的小数位数; 同时,toFixed会进行四舍五入

问题就出在这里,toFixed进行四舍五入时的表现不尽如人意,

image.png

在Chrome浏览器中,实际测试结果:

image.png

所以,当你只是用toFixed来进行补零,也就是说num.toFixed(n)中,n >= num时toFixed才是安全的;当n < num时,它会自动进行四舍五入,但是它四舍五入的结果又不对,我们项目中之前toFixed参与了大量的计算,导致精度丢失,所以我现在正在修复这些问题

image.png

当你需要用toFixed,并且希望它的四舍五入是正确的,这里提供2种解决思路:

1、使用decimal.js

import Decimal from 'decimal.js'


    var num = 1.335
    console.log('toFixed', num.toFixed(2)) // 1.33
    console.log('Decimal', Decimal(num).toFixed(2)) // 1.34

或者是其他库:number-precision/bignumber.js,看你们项目中用的是哪个

2、重写toFixed方法

    // 重写toFixed方法
    Number.prototype.toFixed = function (n) {
      if (n > 20 || n < 0) {
        throw new RangeError(
          'toFixed() digits argument must be between 0 and 20'
        )
      }
      const number = this
      if (isNaN(number) || number >= Math.pow(10, 21)) {
        return number.toString()
      }
      if (typeof n == 'undefined' || n == 0) {
        return Math.round(number).toString()
      }
      let result = number.toString()
      const arr = result.split('.')
      // 整数的情况
      if (arr.length < 2) {
        result += '.'
        for (let i = 0; i < n; i += 1) {
          result += '0'
        }
        return result
      }
      const integer = arr[0]
      const decimal = arr[1]
      if (decimal.length == n) {
        return result
      }
      if (decimal.length < n) {
        for (let i = 0; i < n - decimal.length; i += 1) {
          result += '0'
        }
        return result
      }
      result = integer + '.' + decimal.substr(0, n)
      const last = decimal.substr(n, 1)
      // 四舍五入,转换为整数再处理,避免浮点数精度的损失
      if (parseInt(last, 10) >= 5) {
        const x = Math.pow(10, n)
        result = (Math.round(parseFloat(result) * x) + 1) / x
        result = result.toFixed(n)
      }
      return result
    }

如果你觉得这篇文章对你有用,可以看看作者封装的库xtt-utils,里面封装了非常实用的js方法。如果你也是vue开发者,那更好了,除了常用的api,还有大量的基于element-ui组件库二次封装的使用方法和自定义指令等,帮你提升开发效率。不定期更新,欢迎交流~