利用Math.js解決JS計算小數精度丟失問題
緣由
最近在做公司的一個點餐H5項目需要前端動態(tài)計算用戶選的商品的總價(單價*數量)和購物車的總價格時發(fā)現關于 JavaScript 浮點數計算精度不準確問題。在控制臺輸入0.1+0.2也能發(fā)現此問題。
// 加法
0.1 + 0.2 = 0.30000000000000004
0.7 + 0.1 = 0.7999999999999999
0.2 + 0.4 = 0.6000000000000001
// 減法
1.5 - 1.2 = 0.30000000000000004
0.3 - 0.2 = 0.09999999999999998
// 乘法
19.9 * 100 = 1989.9999999999998
0.8 * 3 = 2.4000000000000004
35.41 * 100 = 3540.9999999999995
// 除法
0.3 / 0.1 = 2.9999999999999996
0.69 / 10 = 0.06899999999999999問題的原因
為什么 0.1+0.2 JS加不了? 產生浮點數計算精度不準確的原因: 在計算機角度,計算機算的是二進制,而不是十進制。二進制后變成了無線不循環(huán)的數,而計算機可支持浮點數的小數部分可支持到52位,所有兩者相加,在轉換成十進制,得到的數就不準確了,加減乘除運算原理一樣。
| 十進制 | 二進制 |
|---|---|
| 0.1 | 0.0001 1001 1001 1001 ... |
| 0.2 | 0.0011 0011 0011 0011 ... |
| 0.3 | 0.0100 1100 1100 1100 ... |
| 0.4 | 0.0110 0110 0110 0110 ... |
| 0.5 | 0.1 |
| 0.6 | 0.1001 1001 1001 1001 ... |
所以兩者相加之后得到這么一串 0.0100110011001100110011001100110011001100110011001100 因浮點數小數位的限制而截斷的二進制數字,這時候,我們再把它轉換為十進制,就成了 0.30000000000000004。
最通俗的解釋
比如一個數 1÷3=0.33333333...... 大家都知道3會一直無限循環(huán),數學可以表示,但是計算機要存儲,方便下次取出來再使用,但0.333333...... 這個數 無限循環(huán),你讓計算機怎么存儲?計算機再大的內存它也存不下,對吧! 所以不能存儲一個相對于數學來說的值,只能存儲一個近似值,所以當計算機存儲后再取出來用時就會出現精度問題。
解決方案 - Math.js
對于任意精度的計算,math.js 支持BigNumber 數據類型。
安裝
npm install mathjs
請注意,在 TypeScript 項目中使用 mathjs 時,您還必須安裝類型定義文件:npm install @types/mathjs.
封裝
import * as math from 'mathjs';
export default {
// 加
add(num1,num2){
return math.add(math.bignumber(num1),math.bignumber(num2));
},
// 乘
multiply(num1,num2){
return math.multiply(math.bignumber(num1),math.bignumber(num2));
},
// 減
subtract(num1,num2){
return math.subtract(math.bignumber(num1),math.bignumber(num2));
},
// 除
divide(num1,num2){
return math.divide(math.bignumber(num1),math.bignumber(num2));
}
}使用
import math from './math.js' let addNum = math.add(3,2); // 5 let mulNum = math.multiply(3,2); // 6 let subNum = math.subtract(3,2); // 1 let divNum = math.divide(3,2); // 1.5
附:math.js 大數功能
<script type="text/javascript">
// functions and constants
console.log('mathjs BigNumber eg')
print(math.add(math.bignumber(0.1), math.bignumber(0.2))) // 加法 BigNumber, 0.3
print(math.subtract(math.bignumber(1), math.bignumber(0.9))) // 減法 BigNumber, 0.1
print(math.multiply(math.bignumber(4.10), math.bignumber(100))) // 乘法 BigNumber, 0.1
print(math.ceil(math.bignumber(6.10)/ math.bignumber(0.1))); //除法 向上取整 61
print(math.floor(math.bignumber(6.10)/ math.bignumber(0.1))); //除法 向下取整 61
print(math.round(math.bignumber(6.10)/ math.bignumber(0.1))); // 除法 四舍五入 61
/**
* Helper function to output a value in the console. Value will be formatted.
* @param {*} value
*/
function print (value) {
const precision = 14
console.log(math.format(value, precision))
}
</script>總結
到此這篇關于利用Math.js解決JS計算小數精度丟失問題的文章就介紹到這了,更多相關JS計算小數精度丟失內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解JavaScript中的Unescape()和String() 函數
這篇文章主要介紹了詳解JavaScript中的unescape()和String() 函數,JavaScript unescape() 函數可對通過 escape() 編碼的字符串進行解碼,String() 函數把對象的值轉換為字符串,對本文感興趣的朋友一起學習吧2015-11-11
JavaScript中的property和attribute介紹
JavaScript中的property和attribute介紹,需要的朋友可以參考下。2011-12-12
設為首頁和收藏的Javascript代碼(親測兼容IE,Firefox,chrome等瀏覽器)
這篇文章主要介紹了設為首頁和收藏的Javascript代碼(親測兼容IE,Firefox,chrome等瀏覽器)。需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11

