JS數字精度丟失的原因及解決方案
前言
在JavaScript中計算兩個十進制數的和,有時候會出現(xiàn)令人驚訝的結果,相信這個大家也都知道了!
精度丟失
例如,我們在計算0.1 + 0.1得到的結果是0.2,但是計算0.1 + 0.2的結果并不是0.3,而是0.30000000000000004
這種現(xiàn)象不僅出現(xiàn)在加法,在減法中也會出現(xiàn)類似的結果。
例如1.2 - 1的結果是0.19999999999999996
不過這并不是JavaScript獨有的,其他編程語言也會存在同樣的問題。
例如在Python環(huán)境下輸出。
print(.1 + .2)
得到的結果同樣是:0.30000000000000004
原因
這個問題的主要原因是計算機將數據存儲為二進制。
如何將整數從十進制轉換為二進制
十進制整數可以通過將其除以 2 轉換為二進制。取商,并繼續(xù)除以 2,直到達到零。
每次執(zhí)行此除法時,請記下余數。現(xiàn)在反轉余數列表,得到二進制形式的數字。
舉個例子,我想把29轉成二進制:
29÷2=14余1
14÷2=7余0
7÷2=3余1
3÷2=1余1
1÷2=0余1
代表十進制 29 的二進制數是11101.
例如:
1 也就是1
10 也就是1010
將小數從十進制轉換為二進制
十進制小數轉換成二進制小數采用"乘2取整,順序排列"法。具體做法是:用2乘十進制小數,可以得到積,將積的整數部分取出,再用2乘余下的小數部分,又得到一個積,再將積的整數部分取出,如此進行,直到積中的小數部分為零,此時0或1為二進制的最后一位?;蛘哌_到所要求的精度為止。
舉個例子:我想把0.375轉成二進制:
0.375*2=0.75 得到0
0.75*2=1.5得到1
0.5*2=1 得到1,小數沒了,結束。最終轉為二進制是0.011
例如:
- 0.1 也就是0.0001100110011001100110011001100110011001100110011001101
- 0.2 也就是0.001100110011001100110011001100110011001100110011001101
并非每個十進制數都可以用這種二進制格式完美表示,因為有些數字可能轉成
JavaScript 在計算時,會先將10進制轉為二進制,在進行計算。
0.00011001100110011001100110011001100110011001100110011010 + 0.0011001100110011001100110011001100110011001100110011010 = 0.0100110011001100110011001100110011001100110011001100111
這里得到的結果0.0100110011001100110011001100110011001100110011001100111再轉換成十進制就是0.30000000000000004
解決方案
第三方庫
Decimal
x = new Decimal(0.1) y = x.plus(0.2)
bignumber
x = new BigNumber(0.1) y = x.plus(0.2)
變成整數
主要思想是:將小數先轉換成拆分兩個字符串,然后計算小數部分的字符串的長度,然后利用這個長度將小數變成整數!
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;
}總結
到此這篇關于JS數字精度丟失的原因分析及解決的文章就介紹到這了,更多相關JS數字精度丟失內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#中TrimStart,TrimEnd,Trim在javascript上的實現(xiàn)
今天在后臺寫了個類,后來才發(fā)現(xiàn),需要在JS上做..于是把代碼拷到js上進行修改,代碼中用到TrimStart,TrimEnd,Trim等方法,在網上找半天竟然沒找到.要么就只能清除空格的!2011-01-01
Jquery和JS用外部變量獲取Ajax返回的參數值的方法實例(超簡單)
Jquery和JS用外部變量獲取Ajax返回的參數值的方法實例(超簡單),需要的朋友可以參考一下2013-06-06

