js计算浮点数出现小数;解决js计算小数问题;js数组相加出现小数;

36 篇文章 1 订阅

原博1 原博2

方案1和方案2都是有效的

=====注意参数一定要是数字 而不能是字符串 否则会计算错误 =====

情景: 在计算浮点数时候,出现多余小数。
例如: 1.11 + 1 = 2.1100000000000003
[外链图片转存失败,源站可能有防盗在这里插入!链机制,建描述1]议将图片上https://传(imblog.cnimg.sg/na5c4ca3Nz9210e64f59acf9d40e5b8f.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_52,text_Q1NETiBAaV9hbV9hX4Rpdl_ml6Xnp6_mnIjntK9f,size_20,color_FFFFFF,t_70,g_se,x_146026)(1)]

为什么计算小数会出现误差?
浮点数值的最高进度是17位小数,但在进行运算的时候其精确度却远远不如整数;整数在进行运算的时候都会转成10进制; 而Java和JavaScript中计算小数运算时,都会先将十进制的小数换算到对应的二进制,一部分小数并不能完整的换算为二进制,这里就出现了第一次的误差。待小数都换算为二进制后,再进行二进制间的运算,得到二进制结果。然后再将二进制结果换算为十进制,这里通常会出现第二次的误差。

方案1:简单的js加法和减法:

//加法
Math.round((parseFloat(num1) + parseFloat(num2))*100)/100
//减法
Math.round((parseFloat(num1) - parseFloat(num2))*100)/100

方案2:复杂的加减乘除运算封装:

以下代码可以直接复制使用

有效的话请点赞评论下,让更多的朋友能够看到解决问题!

<template>
  <div style="padding:20px;">

    <div><span>1.11 + 1 = {{ 1.11 + 1 }}</span> <span>-----处理浮点计算:{{ addNum }}</span></div>
    <div><span>1.11 - 1 = {{ 1.11 - 1 }}</span> <span>-----处理浮点计算:{{ subNum }}</span></div>
    <div><span>1.11 * 100= {{ 1.11 * 100 }}</span> <span>-----处理浮点计算:{{ mulNum }}</span></div>
    <div><span>0.11 / 0.1 = {{ 0.11 / 0.1 }}</span> <span>-----处理浮点计算:{{ divNum }}</span></div>
    <div><span> (((1.11 + 1) - 1) * 100) / 0.1 = {{ (((1.11 + 1) - 1) * 100) / 0.1 }}</span> <span>-----处理浮点计算:{{ lastNum }}</span></div>

  </div>
</template>

<script>

export default {
  data () {
    return {
      addNum: 0,
      subNum: 0,
      mulNum: 0,
      divNum: 0,
      lastNum: 0
    }
  },
  created () {
    this.getNum()
  },
  methods: {
    getNum () {
      console.log(1.11 + 1)
      console.log(1.11 - 1)
      console.log(1.11 * 100)
      console.log(0.11 / 0.1)
      console.log((((1.11 + 1) - 1) * 100) / 0.1)

	  // ================注意参数一定要是数字 而不能是字符串 否则会计算错误 ====================
      this.addNum = this.floatObj().add(1.11, 1)// 加法
      this.subNum = this.floatObj().subtract(1.11, 1)// 减法
      this.mulNum = this.floatObj().multiply(1.11, 100)// 乘法
      this.divNum = this.floatObj().divide(0.11, 0.1)// 除法
      this.lastNum = this.floatObj().divide(this.floatObj().multiply(this.floatObj().subtract(this.floatObj().add(1.11, 1), 1), 100), 0.1)// 混合运算
    },

    /** * 封装了加减乘除四种计算方法 **
     // ================注意参数一定要是数字 而不能是字符串 否则会计算错误 ====================
     *  add / subtract / multiply /divide
     * this.floatObj().add(1.11, 1)// 加法
     * this.floatObj().subtract(1.11, 1)// 减法
     * this.floatObj().multiply(1.11, 100)// 乘法
     * this.floatObj().divide(0.11, 0.1)// 除法
     */
    floatObj () {
      // 判断obj是否为一个整数
      function isInteger (obj) {
        return Math.floor(obj) === obj
      }
      /*
       * 将一个浮点数转成整数,返回整数和倍数。如 3.14 >> 314,倍数是 100
       * @param floatNum {number} 小数
       * @return {object}
       * {times:100, num: 314}
       */
      function toInteger (floatNum) {
        var ret = { times: 1, num: 0 }
        if (isInteger(floatNum)) {
          ret.num = floatNum
          return ret
        }
        var strfi = floatNum + ''
        var dotPos = strfi.indexOf('.')
        var len = strfi.substr(dotPos + 1).length
        var times = Math.pow(10, len)
        var intNum = Number(floatNum.toString().replace('.', ''))
        ret.times = times
        ret.num = intNum
        return ret
      }
      /*
       * 核心方法,实现加减乘除运算,确保不丢失精度
       * 思路:把小数放大为整数(乘),进行算术运算,再缩小为小数(除)
       *
       * @param a {number} 运算数1
       * @param b {number} 运算数2
       * @param op {string} 运算类型,有加减乘除(add/subtract/multiply/divide)
       *
       */
      function operation (a, b, op) {
        var o1 = toInteger(a)
        var o2 = toInteger(b)
        var n1 = o1.num
        var n2 = o2.num
        var t1 = o1.times
        var t2 = o2.times
        var max = t1 > t2 ? t1 : t2
        var result = null
        switch (op) {
          case 'add':
            if (t1 === t2) { // 两个小数位数相同
              result = n1 + n2
            } else if (t1 > t2) { // o1 小数位 大于 o2
              result = n1 + n2 * (t1 / t2)
            } else { // o1 小数位 小于 o2
              result = n1 * (t2 / t1) + n2
            }
            return result / max
          case 'subtract':
            if (t1 === t2) {
              result = n1 - n2
            } else if (t1 > t2) {
              result = n1 - n2 * (t1 / t2)
            } else {
              result = n1 * (t2 / t1) - n2
            }
            return result / max
          case 'multiply':
            result = (n1 * n2) / (t1 * t2)
            return result
          case 'divide':
            result = (n1 / n2) * (t2 / t1)
            return result
        }
      }
      // 加减乘除的四个接口
      function add (a, b) { // 加法
        return operation(a, b, 'add')
      }
      function subtract (a, b) { // 减法
        return operation(a, b, 'subtract')
      }
      function multiply (a, b) { // 乘法
        return operation(a, b, 'multiply')
      }
      function divide (a, b) { // 除法
        return operation(a, b, 'divide')
      }
      return {
        add: add,
        subtract: subtract,
        multiply: multiply,
        divide: divide
      }
    }

  }
}
</script>

<style>
</style>

有效的话请点赞评论下,让更多的朋友能够看到解决问题!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值