解决js浮点数运算的精度问题

在javascript中进行运算的时候经常会出现浮点数的问题,导致运算结果不准确
比如:0.1 + 0.2 = 0.30000000000000004

完整demo及解决方案如下:


<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>demotitle>
    <style>
      .num-tags,
      .total-tag {
        text-align: center;
      }
      i {
        font-style: normal;
      }
      #totalTag {
        color: red;
      }
    style>
  head>
  <body>
    <div class="num-tags">
      <label for="moneys1">数值1:label>
      <input type="text" class="moneys" value="" onkeyup="checkInput(this)" onblur="checkNum(this)" />
      <label for="moneys2">数值2:label>
      <input type="text" class="moneys" value="" onkeyup="checkInput(this)" onblur="checkNum(this)" />
      <button type="button" id="calculates">求和button>
    div>
    <div class="total-tag"><i>合计:i><span id="totalTag">span>div>

    <script>
      document.getElementById('calculates').onclick = function () {
        var countSum = 0
        var nums = document.querySelectorAll('.moneys')
        for (var i = nums.length; i--; ) {
          // 在两值相加时,调用升幂降幂函数
          countSum = formatNum((countSum += parseFloat(nums[i].value)), 10)
        }
        // 为确保计算精度,在赋值之前调用保留两位小数的函数
        document.getElementById('totalTag').innerText = toDecimal2(countSum)
      }

      function checkInput(_this) {
        if (_this.value != '' && _this.value.substr(0, 1) == '.') {
          _this.value = 0
        }
        if (_this.value == '') {
          _this.value = 0
        }
        _this.value = _this.value.replace(/^0*(0\.|[1-9])/, '$1') // 禁止粘贴
        _this.value = _this.value.replace(/[^\d.]/g, '0.00') // 禁止输入非数字
        _this.value = _this.value.replace(/\.{2,}/g, '.') // 只保留第一个. 清除多余的
        _this.value = _this.value.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
        _this.value = _this.value.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3') // 只能输入两个小数

        if (_this.value.indexOf('.') < 0 && _this.value != '') {
          // 以上已经过滤,此处控制的是如果没有小数点,首位不能为类似于 01、02的金额
          if (_this.value.substr(0, 1) == '0' && _this.value.length == 2) {
            _this.value = _this.value.substr(1, _this.value.length)
          }
        }
        if (!_this.value) {
          _this.value = 0
        }
      }

      function checkNum(_this) {
        // 失去焦点的时候判断 如果最后一位是 . 末尾补0
        _this.value.endsWith('.') ? (_this.value += '0') : _this.value
      }

      // 保留两位小数
      function toDecimal2(x) {
        var f = parseFloat(x)
        if (isNaN(f)) {
          return false
        }
        var f = Math.round(x * 100) / 100
        var s = f.toString()
        var rs = s.indexOf('.')
        if (rs < 0) {
          rs = s.length
          s += '.'
        }
        while (s.length <= rs + 2) {
          s += '0'
        }
        return s
      }

      // 把需要计算的数字乘以 10 的 n 次幂,换算成计算机能够精确识别的整数,然后再除以 10 的 n 次幂
      function formatNum(f, digit) {
        var m = Math.pow(10, digit)
        return parseInt(f * m, 10) / m
      }
    script>
  body>
html>

你可能感兴趣的:(js,javascript)