处理小数点精度问题

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script>
      var floatObj = (function () {
        /*
         * 判断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
          }

          // 将传过来小数转化为字符串 0.2转换为'0.2'
          var strfi = floatNum + ''
          // 查找小数点的位置  1
          var dotPos = strfi.indexOf('.')
          // 获取小数点后边有几位   0.2的话 后边就有1;   0.03 后边就有2
          var len = strfi.substr(dotPos + 1).length
          // 放大多少倍   0.2的话就是10*10 ; 0.03的话就是10*10*10
          var times = Math.pow(10, len)
          // 去掉小数点 (将小数点替换成'')  0.2的话 就是 2; 3.03 的话小数点后边就是303
          var intNum = Number(floatNum.toString().replace('.', ''))
          ret.times = times
          ret.num = intNum
          return ret
        }

        /*
         * 核心方法,实现加减乘除运算,确保不丢失精度
         * 思路:把小数放大为整数(乘),进行算术运算,再缩小为小数(除)
         *
         * @param a {number} 运算数1
         * @param b {number} 运算数2
         * @param digits {number} 精度,保留的小数点数,比如 2, 即保留为两位小数
         * @param op {string} 运算类型,有加减乘除(add/subtract/multiply/divide)
         *
         */
        function operation(a, b, digits, 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, digits) {
          return operation(a, b, digits, 'add')
        }
        function subtract(a, b, digits) {
          return operation(a, b, digits, 'subtract')
        }
        function multiply(a, b, digits) {
          return operation(a, b, digits, 'multiply')
        }
        function divide(a, b, digits) {
          return operation(a, b, digits, 'divide')
        }

        // exports
        return {
          add: add,
          subtract: subtract,
          multiply: multiply,
          divide: divide
        }
      })()

      console.log(floatObj.add(0.2, 3.3))
    </script>
  </head>

  <body></body>
</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值