強烈建議使用庫來代替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
驗證以上問題的代碼以下
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
————————————————————————————————————————————————————---
推薦的一些庫