利用Math.js解決JS計(jì)算小數(shù)精度丟失問(wèn)題
緣由
最近在做公司的一個(gè)點(diǎn)餐H5項(xiàng)目需要前端動(dòng)態(tài)計(jì)算用戶選的商品的總價(jià)(單價(jià)*數(shù)量)和購(gòu)物車的總價(jià)格時(shí)發(fā)現(xiàn)關(guān)于 JavaScript 浮點(diǎn)數(shù)計(jì)算精度不準(zhǔn)確問(wèn)題。在控制臺(tái)輸入0.1+0.2也能發(fā)現(xiàn)此問(wè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問(wèn)題的原因
為什么 0.1+0.2 JS加不了? 產(chǎn)生浮點(diǎn)數(shù)計(jì)算精度不準(zhǔn)確的原因: 在計(jì)算機(jī)角度,計(jì)算機(jī)算的是二進(jìn)制,而不是十進(jìn)制。二進(jìn)制后變成了無(wú)線不循環(huán)的數(shù),而計(jì)算機(jī)可支持浮點(diǎn)數(shù)的小數(shù)部分可支持到52位,所有兩者相加,在轉(zhuǎn)換成十進(jìn)制,得到的數(shù)就不準(zhǔn)確了,加減乘除運(yùn)算原理一樣。
| 十進(jìn)制 | 二進(jìn)制 |
|---|---|
| 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 因浮點(diǎn)數(shù)小數(shù)位的限制而截?cái)嗟亩M(jìn)制數(shù)字,這時(shí)候,我們?cè)侔阉D(zhuǎn)換為十進(jìn)制,就成了 0.30000000000000004。
最通俗的解釋
比如一個(gè)數(shù) 1÷3=0.33333333...... 大家都知道3會(huì)一直無(wú)限循環(huán),數(shù)學(xué)可以表示,但是計(jì)算機(jī)要存儲(chǔ),方便下次取出來(lái)再使用,但0.333333...... 這個(gè)數(shù) 無(wú)限循環(huán),你讓計(jì)算機(jī)怎么存儲(chǔ)?計(jì)算機(jī)再大的內(nèi)存它也存不下,對(duì)吧! 所以不能存儲(chǔ)一個(gè)相對(duì)于數(shù)學(xué)來(lái)說(shuō)的值,只能存儲(chǔ)一個(gè)近似值,所以當(dāng)計(jì)算機(jī)存儲(chǔ)后再取出來(lái)用時(shí)就會(huì)出現(xiàn)精度問(wèn)題。
解決方案 - Math.js
對(duì)于任意精度的計(jì)算,math.js 支持BigNumber 數(shù)據(jù)類型。
安裝
npm install mathjs
請(qǐng)注意,在 TypeScript 項(xiàng)目中使用 mathjs 時(shí),您還必須安裝類型定義文件: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計(jì)算小數(shù)精度丟失問(wèn)題的文章就介紹到這了,更多相關(guān)JS計(jì)算小數(shù)精度丟失內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
返回頁(yè)面頂部top按鈕通過(guò)錨點(diǎn)實(shí)現(xiàn)(自寫(xiě))
用戶在使用系統(tǒng)時(shí),會(huì)有很多表單的操作然而很多表單就會(huì)很長(zhǎng),所以就需要一個(gè)返回頁(yè)面頂部的top按鈕啦,于是自己寫(xiě)了一個(gè),喜歡的朋友可以參考下2013-08-08
es6函數(shù)之嚴(yán)格模式用法實(shí)例分析
這篇文章主要介紹了es6函數(shù)之嚴(yán)格模式用法,結(jié)合實(shí)例形式分析了es6函數(shù)嚴(yán)格模式的定義、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-03-03
uniapp上傳圖片和上傳視頻的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于uniapp上傳圖片和上傳視頻的實(shí)現(xiàn)方法,文中還介紹了上傳文件的方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01
詳解JavaScript中的Unescape()和String() 函數(shù)
這篇文章主要介紹了詳解JavaScript中的unescape()和String() 函數(shù),JavaScript unescape() 函數(shù)可對(duì)通過(guò) escape() 編碼的字符串進(jìn)行解碼,String() 函數(shù)把對(duì)象的值轉(zhuǎn)換為字符串,對(duì)本文感興趣的朋友一起學(xué)習(xí)吧2015-11-11
JavaScript中的property和attribute介紹
JavaScript中的property和attribute介紹,需要的朋友可以參考下。2011-12-12
設(shè)為首頁(yè)和收藏的Javascript代碼(親測(cè)兼容IE,Firefox,chrome等瀏覽器)
這篇文章主要介紹了設(shè)為首頁(yè)和收藏的Javascript代碼(親測(cè)兼容IE,Firefox,chrome等瀏覽器)。需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-11-11

