JS數(shù)字精度丟失的原因及解決方案
前言
在JavaScript中計(jì)算兩個(gè)十進(jìn)制數(shù)的和,有時(shí)候會(huì)出現(xiàn)令人驚訝的結(jié)果,相信這個(gè)大家也都知道了!
精度丟失
例如,我們?cè)谟?jì)算0.1 + 0.1得到的結(jié)果是0.2,但是計(jì)算0.1 + 0.2的結(jié)果并不是0.3,而是0.30000000000000004
這種現(xiàn)象不僅出現(xiàn)在加法,在減法中也會(huì)出現(xiàn)類似的結(jié)果。
例如1.2 - 1的結(jié)果是0.19999999999999996
不過(guò)這并不是JavaScript獨(dú)有的,其他編程語(yǔ)言也會(huì)存在同樣的問(wèn)題。
例如在Python環(huán)境下輸出。
print(.1 + .2)
得到的結(jié)果同樣是:0.30000000000000004
原因
這個(gè)問(wèn)題的主要原因是計(jì)算機(jī)將數(shù)據(jù)存儲(chǔ)為二進(jìn)制。
如何將整數(shù)從十進(jìn)制轉(zhuǎn)換為二進(jìn)制
十進(jìn)制整數(shù)可以通過(guò)將其除以 2 轉(zhuǎn)換為二進(jìn)制。取商,并繼續(xù)除以 2,直到達(dá)到零。
每次執(zhí)行此除法時(shí),請(qǐng)記下余數(shù)?,F(xiàn)在反轉(zhuǎn)余數(shù)列表,得到二進(jìn)制形式的數(shù)字。
舉個(gè)例子,我想把29轉(zhuǎn)成二進(jìn)制:
29÷2=14余1
14÷2=7余0
7÷2=3余1
3÷2=1余1
1÷2=0余1
代表十進(jìn)制 29 的二進(jìn)制數(shù)是11101.
例如:
1 也就是1
10 也就是1010
將小數(shù)從十進(jìn)制轉(zhuǎn)換為二進(jìn)制
十進(jìn)制小數(shù)轉(zhuǎn)換成二進(jìn)制小數(shù)采用"乘2取整,順序排列"法。具體做法是:用2乘十進(jìn)制小數(shù),可以得到積,將積的整數(shù)部分取出,再用2乘余下的小數(shù)部分,又得到一個(gè)積,再將積的整數(shù)部分取出,如此進(jìn)行,直到積中的小數(shù)部分為零,此時(shí)0或1為二進(jìn)制的最后一位。或者達(dá)到所要求的精度為止。
舉個(gè)例子:我想把0.375轉(zhuǎn)成二進(jìn)制:
0.375*2=0.75 得到0
0.75*2=1.5得到1
0.5*2=1 得到1,小數(shù)沒(méi)了,結(jié)束。最終轉(zhuǎn)為二進(jìn)制是0.011
例如:
- 0.1 也就是0.0001100110011001100110011001100110011001100110011001101
- 0.2 也就是0.001100110011001100110011001100110011001100110011001101
并非每個(gè)十進(jìn)制數(shù)都可以用這種二進(jìn)制格式完美表示,因?yàn)橛行?shù)字可能轉(zhuǎn)成
JavaScript 在計(jì)算時(shí),會(huì)先將10進(jìn)制轉(zhuǎn)為二進(jìn)制,在進(jìn)行計(jì)算。
0.00011001100110011001100110011001100110011001100110011010 + 0.0011001100110011001100110011001100110011001100110011010 = 0.0100110011001100110011001100110011001100110011001100111
這里得到的結(jié)果0.0100110011001100110011001100110011001100110011001100111再轉(zhuǎn)換成十進(jìn)制就是0.30000000000000004
解決方案
第三方庫(kù)
Decimal
x = new Decimal(0.1) y = x.plus(0.2)
bignumber
x = new BigNumber(0.1) y = x.plus(0.2)
變成整數(shù)
主要思想是:將小數(shù)先轉(zhuǎn)換成拆分兩個(gè)字符串,然后計(jì)算小數(shù)部分的字符串的長(zhǎng)度,然后利用這個(gè)長(zhǎng)度將小數(shù)變成整數(shù)!
function add(num1, num2) { const num1Len = (num1.toString().split('.')[1] ).length; const num2Len = (num2.toString().split('.')[1] ).length; const maxLen = Math.pow(10, Math.max(num1Len, num2Len)); return (num1 * maxLen + num2 * maxLen) / maxLen; }
總結(jié)
到此這篇關(guān)于JS數(shù)字精度丟失的原因分析及解決的文章就介紹到這了,更多相關(guān)JS數(shù)字精度丟失內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章

C#中TrimStart,TrimEnd,Trim在javascript上的實(shí)現(xiàn)

跟我學(xué)習(xí)javascript的undefined與null

Jquery和JS用外部變量獲取Ajax返回的參數(shù)值的方法實(shí)例(超簡(jiǎn)單)

javaScript中一些常見(jiàn)的數(shù)據(jù)類型檢查校驗(yàn)