公共

强烈建议使用库来代替JS原生的四则运算,原因如下

  • 0.1 + 0.2 = 0.30000000000000004
  • 0.105.toFixed(2) = 0.10 // not 0.11 采用toFixed并不能得到正确的值,很多人忽略这个问题
  • 0.106.toFixed(2) = 0.11 // not 0.10
  • 在对精度要求不高的场合可以使用原有的四则运算,10000组100个随机数随机运算后保留0位小数,只有3组相差1

验证以上问题的代码如下

  • 该代码使用 decimal.js 库辅助验证
    import Decimal from 'decimal.js'

    const numsTotal = 80
    const repetitions = 1000
    const fixed = 4

    let differenceTotal = 0
    let differenceArr = []

    function numsMath() {
      let nums = []
      let methods = []
      for (let i = 0; i < numsTotal; i++) {
        nums.push(parseFloat(Math.random().toFixed(2)))
        methods.push(Math.floor(Math.random() * 4))
      }
      let total = 0
      let decimalTotal = 0
      nums.forEach((item, index) => {
        switch (methods[index]) {
          case 0:
            total += item
            decimalTotal = new Decimal(decimalTotal).add(new Decimal(item)).toNumber()
            break;
          case 1:
            total -= item
            decimalTotal = new Decimal(decimalTotal).sub(new Decimal(item)).toNumber()
            break;
          case 2:
            total *= item
            decimalTotal = new Decimal(decimalTotal).mul(new Decimal(item)).toNumber()
            break;
          case 3:
            total /= item
            decimalTotal = new Decimal(decimalTotal).div(new Decimal(item)).toNumber()
            break;
          default:
            break;
        }
      })
      if (total.toFixed(fixed) !== decimalTotal.toFixed(fixed)) {
        differenceTotal++
        differenceArr.push({
          nums,
          methods,
          total,
          decimalTotal
        })
      }
    }
    for (let i = 0; i < repetitions; i++) {
      numsMath()
    }
    console.log('differenceTotal =>', differenceTotal)
    console.log('differenceArr =>', differenceArr)

——————————————————————————————————————————————————————

Number 相关知识点

  • 能够正确显示总位数为16的小数,并做出判断(前面为0时总共17位)(不包含符号位)
 0.09999999999999999 === 0.09999999999999998 // false 09999999999999998一共17位
 0.009999999999999999 === 0.009999999999999998 // true

 0.9999999999999999 === 0.9999999999999998 // false 9999999999999998一共16位
-0.9999999999999999 === -0.9999999999999998 // false
 1.9999999999999999 === 1.9999999999999998 // false
-1.9999999999999999 === -1.9999999999999998 // false

2.9999999999999999 === 2.9999999999999998 // true
10.9999999999999999 === 10.9999999999999998 // true

 2.999999999999999 === 2.999999999999998 // false 999999999999998一共15位
-2.999999999999999 === -2.999999999999998 // false
 10.999999999999999 === 10.999999999999998 // true 999999999999998一共15位

 10.99999999999999 === 10.99999999999998 // false 99999999999998一共14位
-10.99999999999999 === -10.99999999999998 // false

Number.MAX_SAFE_INTEGER

  • 在 JavaScript 中整数和浮点数都属于 Number 数据类型,所有数字都是以 64 位浮点数形式储存,即便整数也是如此。
  • Number.MAX_SAFE_INTEGER 常量表示在 JavaScript 中最大的安全整数。
  • MAX_SAFE_INTEGER 是一个值为 9007199254740991的常量。
  • 因为Javascript的数字存储使用了 IEEE 754 中规定的双精度浮点数数据类型
  • 这里安全存储的意思是指能够准确区分两个不相同的值,例如 Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 将得到 true的结果,而这在数学上是错误的

Number.MIN_SAFE_INTEGER

  • 代表在 JavaScript中最小的安全的integer型数字
  • MIN_SAFE_INTEGER 的值是-9007199254740991

Number.isSafeInteger

  • 用来判断传入的参数值是否是一个“安全整数”
  • IE不兼容?
Number.isSafeInteger(NaN);                  // false
Number.isSafeInteger(Infinity);             // false
Number.isSafeInteger("3");                  // false
Number.isSafeInteger(3.1);                  // false
Number.isSafeInteger(3.0);                  // true
Number.isSafeInteger(Math.pow(2, 53) - 1)   // true

————————————————————————————————————————————————————---

推荐的一些库

原文地址:https://www.cnblogs.com/qq3279338858/p/10652882.html