利用Math.js解決JS計算小數(shù)精度丟失問題
緣由
最近在做公司的一個點餐H5項目需要前端動態(tài)計算用戶選的商品的總價(單價*數(shù)量)和購物車的總價格時發(fā)現(xiàn)關(guān)于 JavaScript 浮點數(shù)計算精度不準確問題。在控制臺輸入0.1+0.2也能發(fā)現(xiàn)此問題。
// 加法 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加不了? 產(chǎn)生浮點數(shù)計算精度不準確的原因: 在計算機角度,計算機算的是二進制,而不是十進制。二進制后變成了無線不循環(huán)的數(shù),而計算機可支持浮點數(shù)的小數(shù)部分可支持到52位,所有兩者相加,在轉(zhuǎn)換成十進制,得到的數(shù)就不準確了,加減乘除運算原理一樣。
十進制 | 二進制 |
---|---|
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 因浮點數(shù)小數(shù)位的限制而截斷的二進制數(shù)字,這時候,我們再把它轉(zhuǎn)換為十進制,就成了 0.30000000000000004。
最通俗的解釋
比如一個數(shù) 1÷3=0.33333333...... 大家都知道3會一直無限循環(huán),數(shù)學可以表示,但是計算機要存儲,方便下次取出來再使用,但0.333333...... 這個數(shù) 無限循環(huán),你讓計算機怎么存儲?計算機再大的內(nèi)存它也存不下,對吧! 所以不能存儲一個相對于數(shù)學來說的值,只能存儲一個近似值,所以當計算機存儲后再取出來用時就會出現(xiàn)精度問題。
解決方案 - Math.js
對于任意精度的計算,math.js 支持BigNumber 數(shù)據(jù)類型。
安裝
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 大數(shù)功能
<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>
總結(jié)
到此這篇關(guān)于利用Math.js解決JS計算小數(shù)精度丟失問題的文章就介紹到這了,更多相關(guān)JS計算小數(shù)精度丟失內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
維護loading加載狀態(tài)的幾個方法小結(jié)
在項目開發(fā)中,當頁面請求接口時,組件局部或者頁面全局顯示loading加載遮罩可謂是司空見慣了,下面來討論一下如何優(yōu)雅的使用loading狀態(tài),文中通過代碼示例介紹的非常詳細,需要的朋友可以參考下2024-09-09javascript原生封裝一個淡入淡出效果的函數(shù)測試實例代碼
這篇文章主要介紹了javascript原生封裝一個淡入淡出效果的函數(shù),主要有FadeIn淡入函數(shù)和FadeOut淡出函數(shù),需要的朋友可以參考下2018-03-03JS數(shù)組合并push與concat區(qū)別分析
這篇文章主要介紹了JS數(shù)組合并push與concat區(qū)別,結(jié)合實例形式分析了JavaScript中針對數(shù)組合并操作使用push與concat的區(qū)別,需要的朋友可以參考下2015-12-12JS實現(xiàn)Enter鍵跳轉(zhuǎn)及控件獲得焦點
想讓Enter鍵跳轉(zhuǎn)的同時讓控件獲得焦點,具體實現(xiàn)js代碼如下,感興趣的朋友可以參考下,希望對大家有所幫助2013-08-08bootstrap與pagehelper實現(xiàn)分頁效果
這篇文章主要為大家詳細介紹了bootstrap與pagehelper實現(xiàn)分頁效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12js數(shù)組循環(huán)遍歷數(shù)組內(nèi)所有元素的方法
在js中數(shù)組遍歷最簡單的辦法就是使用for然后再利用arr.length長度作為for最大限度值即可解決了,下面我們來看看一些有用的實例2014-01-01