解决js toFixed 四舍五入遇5不进位问题

黄良钵

分类: 程序开发 51 0

银行家舍入

const a = 7.55;
console.log(a.toFixed(1)) // 7.5

比如上面这代码,如果作为四舍五入计算的话,就会出现遇到5不进位的问题

具体原因可以参考这篇文章 js - tofixed精度丢失问题

附上上面文章的解决方案的ts版(重写Number.prototype.toFixed

/**
 * 重写toFixed方法,默认toFixed方法遇5不进位
 */
Number.prototype.toFixed = function (n: number) {
  if (n > 20 || n < 0) {
    throw new RangeError('toFixed() digits argument must be between 0 and 20')
  }

  // eslint-disable-next-line @typescript-eslint/no-this-alias
  const number = this

  if (isNaN(number as number) || number >= Math.pow(10, 21)) {
    return number.toString()
  }

  if (typeof n == 'undefined' || n == 0) {
    return Math.round(number as number).toString()
  }

  let result: string | number = 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
}

另一种方法,使用
Math.round
封装,推荐使用:

/**
 * 四舍五入+保留小数
 * @param num 值
 * @param decimal 保留小数的位数
 */
export const toFixed = (num: number, decimal = 0) => {
  if (typeof num === 'undefined') {
    return ''
  }

  if (isNaN(num) || num >= Math.pow(10, 21)) {
    return ''
  }

  // 获取保留几位小数
  const d = Math.pow(10, decimal)
  return (Math.round((num + Number.EPSILON) * d) / d)?.toString()
}

  • 0人 Love
  • 0人 Haha
  • 0人 Wow
  • 0人 Sad
  • 0人 Angry
js、round、toFixed、四舍五入、银行家舍入

作者简介: 黄良钵

打赏

博客站长,前端开发工程师

共 0 条评论关于 “解决js toFixed 四舍五入遇5不进位问题”

Loading...