[JS][深度]關於計算機無法精確處理小數的問題

1、問題

給定一個變量 temp, 變量初始值爲0.1,每次遞增0.1:

let temp = 0.1;
while (temp<10){
    temp+=0.1;
    console.log(temp)
}

打印值部分序列如下:

0.4>0.5>0.6>0.7>0.799999…>0.899999…>0.9999…>1.09999…>0.9999…>1.09999…>0.99999…

注意到從0.7>0.7999…的部分開始,0.7+0.1=0.7999999999

繼續看以下代碼:

<html>	
	<script type="text/javascript" >
		window.onload =function(){
				alert(0.4==0.40000000000000001);//true
		}
	</script>
</html>

很神奇

大概試了一下,從小數位後18位起,計算機就識別不了了。

2、解釋

典型的精度問題,其實不是我們代碼本身的問題。

計算機是以二進制的方式來存儲數據,代碼中的十進制小數,計算機都會替我們轉換爲二進制去進行計算。

作爲小數,在二進制的情形下,會出現無窮小數的狀況。

舉個例子

 

十進制15.43轉換成二進制是多少

整數部分:

15%2=1

(15%2)%2=1

((15%2)%2)%2=1

(((15%2)%2)%2)%2=1  

除二取餘,逆序排列:1111

小數部分:

Math.ceil(0.43*2)=0

Math.ceil((0.43*2)*2)=1

Math.ceil(((0.43*2)*2)*2)=1

Math.ceil((((0.43*2)*2)*2)*2)=0

Math.ceil(((((0.43*2)*2)*2)*2)*2)=1

Math.ceil((((((0.43*2)*2)*2)*2)*2)*2)……

……

乘二取整,順序排列:01101……

把計算出來的整數部分和小數部分放到一起,中間加上小數點

所以15.43二進制爲:1111.01101……

 

可以發現,在計算整數部分的過程中,2的0次方=1,這是整數最小單位,二進制整數以"0"或"1"結尾,相應10進制則表現爲奇數或者偶數,涵蓋了所有自然數,所以不會出現無窮序列的情況。

但小數部分如果不正好等於0.5的n次冪,如例子中的0.43,則二進制轉換的這個過程永遠無法結束。

3、解決方案

所以小數的計算,在項目中進行的應用時,不能直接將其交給計算機進行處理,否則大概率會出問題。

人工干預的方法:將小數類型數據轉化成0.5的n次冪家族中的一員,n由項目實際所需的精度而定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章