最近在做訂單相關的一個功能,涉及到金額的計算,有人建議,將計算全部拋給后端來做吧,前端就不需要再維護一套算法了,話說的在理,但是呢,想想用戶體驗,單價*數量=金額,當用戶改變一個數量時,用戶都口算出來金額了,然而頁面還在請求的loading中,這也太.......
於是乎,我決定前端也維護一套算法,給用戶最快的響應.頁面大致如下:
正常來說,這完全不是個事,很快就全部按要求實現 了,然而,測試過程中,發現了下圖:
什么? 0.14*100=14.0000000000000002 ???
開發這么多年,真的第一次遇到,於是乎開始了各種測試,各種查閱,原來是這樣啊:
js計算時,會將十進制轉換成二進制,再進行計算,但有些小數轉換成二進制時候,出現了無限循環,由於位數有限,所以就出現了截取,所以就導致了再轉化成十進制后結果的不精確.所以就出現了: 0.1+0.2 !== 0.3
不說這些廢話了,直接來解決方案:
math.js 是一款功能強大,使用靈活的數學庫。不過此處我只需使用加減乘除等簡單的方法,需要更多者可以查閱官網
1,引入第三方的js庫, math.js,
math.js的下載地址是:
https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.0.0/math.js。
2,在程序入口處統一配置以下math.js,
//統一配置math.js math.config({ number: 'BigNumber', // 'number' (default), precision: 20 });
3,使用mathjs里的運算方式改寫計算公式:比如,以前的的金額計算如下:
改寫之后為:
//使用math.js轉換數據類型 item.listPrice = math.bignumber(item.listPrice) ; //計算金額:金額=列表價*數量 var amountOfBigNumber = item.listPrice * item.orderNum; //轉換結果類型,提取數字(不轉的話,得到的是對象) item.amount = math.number(amountOfBigNumber);
這樣就不會出現誤差,結果就能正常了,即 0.14 * 100 = 14 !
注:常用的幾個運算方法是:
運算 | 方法名 | 參數 | 備注 |
加 |
math.add(a,b,c,...)
|
參數個數>=2 | 得到幾個數字的和 |
減 |
math.subtract(a,b)
|
參數個數=2 | 得到 a-b 的結果, 不可連減 |
乘 | math.multiply(a,b,c,...) | 參數個數>=2 | 得幾個參數的乘積 |
除 |
math.divide(a,b)
|
參數個數=2 | 得到 a/b 的結果 ,不可連除 |
轉換為bigNumber類型 |
math.bignumber(a)
|
浮點數,進行運算時,轉換成bigNumber才能保證得到精確的結果 | |
轉換為數字類型 |
math.number(a)
|
bignumber為對象,此方法可以獲取對象中的數字部分 |
另外,還有以款比較強大的數學庫,BigNumber.js,同樣能解決我們的問題,有興趣者可以研究下