JS-浮点数计算BUG修复

38次阅读

共计 1536 个字符,预计需要花费 4 分钟才能阅读完成。

遇到的问题

项目下个阶段需要前端进行加点乘除,提前开始准备整理方法函数,就遇到 js 浮点数计算的 bug 问题。

有时候计算的结果跟我们预期不一样,例如

0.1 + 0.2
//0.30000000000000004

1.4 - 0.3
//1.0999999999999999

19.9 * 100 
//1989.9999999999998

24.56 / 100
//0.24559999999999998

原因也了解了,就不在这里多说,网上一大堆。

还有保留小数点时,使用 toFixed 方法会遇到四舍五入有差别,查原因说 toFixed 是遵守四舍六入五留双规则

2.235.toFixed(2)
//'2.23'

解决的办法

写了一个简单的对象修复浮点计算 BUG,里面包含了加、减、乘、除、保留小数点、数字金额化方法
简单使用:

// 加减法,如果需要减就加负数
numberFloat.addOrSub(0.1,0.2,0.4,-0.3) // 结果 0.4

// 乘法
numberFloat.mul(19.9,100,2) // 结果 3980

// 除法
numberFloat.div(19.9,100) // 结果 0.199

// 保留小数
numberFloat.toFixed(2.235, 2) // 结果 2.24

// 格式化
numberFloat.moneyFormat(15243.1456) // 结果 15,243.15
const numberFloat = {getLength(n1) {let arr = n1.toString().split('.')
    return arr.length > 1 ? arr[1].length : 0
  },
  _handleData() {let args = []
    for (let i = 0; i < arguments.length; i++) {args.push(arguments[i])
    }
    let r = args.map(n => {return this.getLength(n)
    })
    const p = Math.max(...r)
    // 扩大之后的数据
    // 每一项扩大 10 的 p 次方
    const c = args.map(n => {return Number(`${n}e${p}`)
    })

    return {c, p}
  },
  // 加减法, 减法就是加负数
  addOrSub() {const { c, p} = this._handleData(...arguments)
    const reducer = (acc, curr) => acc + curr
    let all = c.reduce(reducer, 0)
    return all / Number(`1e${p}`)
  },
  mul() {const { c, p} = this._handleData(...arguments)
    const reducer = (acc, curr) => acc * curr
    let all = c.reduce(reducer, 1)
    return all / Number(`1e${p * arguments.length}`)
  },
  div() {const { c, d} = this._handleData(...arguments)
    const reducer = (acc, curr) => acc ? acc / curr : curr
    let all = c.reduce(reducer)
    return all
  },
  toFixed(count, n) {let round = Math.round(`${count}e${n}`)
    return Number(`${round}e${-n}`).toFixed(n)
  },
  moneyFormat(count) {let mon = this.toFixed(count, 2)
    let reg = /(\d)(?=(\d{3})+\.)/g
    return mon.replace(reg, ($0, $1) => $1 + ',')
  }
}

正文完
 0