js计算精度问题

js计算精度问题

1. 封装js文件 【文件名calculation】

/**
 * 解决js计算的精度问题
 */
const fn = {
  countDecimals(num) {
    let len = 0
    try {
      num = Number(num)
      let str = num.toString().toUpperCase()
      if (str.split('E').length === 2) { // scientific notation
        let isDecimal = false
        if (str.split('.').length === 2) {
          str = str.split('.')[1]
          if (parseInt(str.split('E')[0]) !== 0) {
            isDecimal = true
          }
        }
        let x = str.split('E')
        if (isDecimal) {
          len = x[0].length
        }
        len -= parseInt(x[1])
      } else if (str.split('.').length === 2) { // decimal
        if (parseInt(str.split('.')[1]) !== 0) {
          len = str.split('.')[1].length
        }
      }
    } catch (e) {
      throw e
    } finally {
      if (isNaN(len) || len < 0) {
        len = 0
      }
      // eslint-disable-next-line no-unsafe-finally
      return len
    }
  },
  convertToInt(num) {
    num = Number(num)
    let newNum = num
    let times = this.countDecimals(num)
    let tempNum = num.toString().toUpperCase()
    if (tempNum.split('E').length === 2) {
      newNum = Math.round(num * Math.pow(10, times))
    } else {
      newNum = Number(tempNum.replace('.', ''))
    }
    return newNum
  },
  getCorrectResult(type, num1, num2, result) {
    let tempResult = 0
    switch (type) {
      case 'add':
        tempResult = num1 + num2
        break
      case 'sub':
        tempResult = num1 - num2
        break
      case 'div':
        tempResult = num1 / num2
        break
      case 'mul':
        tempResult = num1 * num2
        break
    }
    if (Math.abs(result - tempResult) > 1) {
      return Number(tempResult)
    }
    return Number(result)
  }
}

const calculation = {
  // 加法
  add(num1, num2) {
    num1 = Number(num1)
    num2 = Number(num2)
    let dec1, dec2, times
    try { dec1 = fn.countDecimals(num1) + 1 } catch (e) { dec1 = 0 }
    try { dec2 = fn.countDecimals(num2) + 1 } catch (e) { dec2 = 0 }
    times = Math.pow(10, Math.max(dec1, dec2))
    // let result = (num1 * times + num2 * times) / times
    let result = (this.mul(num1, times) + this.mul(num2, times)) / times
    return fn.getCorrectResult('add', num1, num2, result)
    // return result
  },
  // 减法
  sub(num1, num2) {
    num1 = Number(num1)
    num2 = Number(num2)
    let dec1, dec2, times
    try { dec1 = fn.countDecimals(num1) + 1 } catch (e) { dec1 = 0 }
    try { dec2 = fn.countDecimals(num2) + 1 } catch (e) { dec2 = 0 }
    times = Math.pow(10, Math.max(dec1, dec2))
    // let result = Number(((num1 * times - num2 * times) / times)
    let result = Number((this.mul(num1, times) - this.mul(num2, times)) / times)
    return fn.getCorrectResult('sub', num1, num2, result)
    // return result
  },
  // 乘法
  mul(num1, num2) {
    num1 = Number(num1)
    num2 = Number(num2)
    let times = 0
    let s1 = num1.toString()
    let s2 = num2.toString()
    try { times += fn.countDecimals(s1) } catch (e) { }
    try { times += fn.countDecimals(s2) } catch (e) { }
    let result = fn.convertToInt(s1) * fn.convertToInt(s2) / Math.pow(10, times)
    return fn.getCorrectResult('mul', num1, num2, result)
    // return result
  },
  // 除法
  div(num1, num2) {
    num1 = Number(num1)
    num2 = Number(num2)
    let t1 = 0
    let t2 = 0
    let dec1, dec2
    try { t1 = fn.countDecimals(num1) } catch (e) { }
    try { t2 = fn.countDecimals(num2) } catch (e) { }
    dec1 = fn.convertToInt(num1)
    dec2 = fn.convertToInt(num2)
    let result = this.mul((dec1 / dec2), Math.pow(10, t2 - t1))
    return fn.getCorrectResult('div', num1, num2, result)
    // return result
  }
}

export default calculation

2. 使用

1. 引入
import  calculation  from "@/api/calculation"

2. 使用
 // 加法
 calculation.add(参数一,参数二)
 // 减法
 calculation.sub(参数一,参数二)
 // 乘法
 calculation.mul(参数一,参数二)
 // 除法
 calculation.div(参数一,参数二)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值