目錄
- ieee754標準
- 解決方法
和c語言一樣,所有以ieee754標準的語言都有浮點數精度問題,js也有浮點數精度問題,并且因為是弱類型語言這個問題更嚴重,js的Number類型的數據都被視為浮點數
ieee754標準
js的數字類型就相當于c語言double類型,是64位的
- 符號位也是首位
- 指數位一共11位,表示指數
- 尾數位一共52位,表示小數點后的數,超出部分舍1進0
所以我們的小數表示只能是2**-1、2**-2、2**-3以此類推
也就是0.5,0.25,0.125
所以像0.1、0.7這些數據就無法精準表示,計算就會出錯
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.7); // 0.7999999999999999
為了驗證該例子,我們得先知道怎么將浮點數轉換為二進制,整數我們可以用除 2 取余的方式,小數我們則可以用乘 2 取整的方式。
將0.1轉為二進制
0.1 * 2,值為 0.2,小數部分 0.2,整數部分 0
0.2 * 2,值為 0.4,小數部分 0.4,整數部分 0
0.4 * 2,值為0.8,小數部分0.8,整數部分0
0.8 * 2,值為 1.6,小數部分 0.6,整數部分 1
0.6 * 2,值為 1.2,小數部分 0.2,整數部分 1
0.2 * 2,值為 0.4,小數部分 0.4,整數部分 0
從 0.2 開始循環,也就是0.00110011001100110…
而0.2的二進制為 0.00110011001100110011…
0.1 + 0.2 = 0.011011…
轉為十進制
0.(02)-1+(12)-2+(1**2)-3…
最終在第52位截取(0舍1入)
所以 0.30000000000000004是這么來的
解決方法
通常這種對精度要求高的計算都應該交給后端去計算和存儲,因為后端有成熟的庫來解決這種計算問題。
前端也有幾個不錯的類庫:
Math.js
Math.js 是專門為 JavaScript 和 Node.js 提供的一個廣泛的數學庫。它具有靈活的表達式解析器,支持符號計算,配有大量內置函數和常量,并提供集成解決方案來處理不同的數據類型。
像數字,大數字(超出安全數的數字),復數,分數,單位和矩陣。 功能強大,易于使用。
decimal.js
為 JavaScript 提供十進制類型的任意精度數值。
big.js
不僅能夠支持處理 Long 類型的數據,也能夠準確的處理小數的運算。