公共 - 浮點計算

強烈建議使用庫來代替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

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

推薦的一些庫

相關文章
相關標籤/搜索