最近小編我在網上閑逛的時候發現有很多用戶都在反映一個非常驚悚的問題:使用Android手機內置的計算器時有些最簡單的減法都會算錯,例如14.52-14.49,再例如8.03-7.96,具體結果各位網友請趕緊拿出自己手上的Android手機算算吧,如果沒有Android手機的話,那就只能看小編我來算了...
▲左邊:14.52-14.49;右邊:8.03-7.96
如上面兩張圖,這個計算錯誤簡直是讓人匪夷所思,而且其實不止這兩道題,會出現問題的數字還有很多很多。這萬一要是考試的時候偷偷作弊掏出來算個題目啥的,那還不直接補考補到死??話說考試作弊是不對,不過這個問題的確很嚴重,而且根據我的調查,身邊使用Android手機的人也基本上都出現了這個問題。真的是google的開發人員犯了如此低級的錯誤嗎?還是另有隱情?請大家關注本期走進科學...
開個玩笑,小編我在發現這個問題之后立馬進行了大量的查證,具體是為啥呢?還是谷歌大神萬能:首先,在我們進行四則運算時計算機需要將十進制的數轉換成二進制,并且因為有小數,所以采用浮點數的方式存儲。如何怎么轉換成二進制?計算方法如下:
整數部分采用 除2 取余數;小數部分采用 乘2 取整數。
以8.03為例:
整數部分:
8/2 =4 余 0
4/2 =2 余 0
2/2 =1 余 0
1/2 =0 余 1
倒序排列取得的余數:1000
小數部分:
0.03 × 2 =0.06 整數 0
0.06 × 2 =0.12 整數 0
0.12 × 2 =0.24 整數 0
0.24 × 2 =0.48 整數 0
0.48 × 2 =0.96 整數 0
0.96 × 2 =1.92 整數 1
0.92 × 2 =1.84 整數 1
0.84 × 2 =1.68 整數 1
小數部分幾乎無窮無盡,但為了方便起見,我們只取前8位就可以了。
正向排列取得的整數:00000111
好了,8.03的二進制表示就是1000.00000111
同理,7.96的二進制表示就是0111.11110101
其次,有了2個數的二進制表示,然后就可以相減了:1000.00000111 - 0111.11110101
豎向排列比較容易看
1000.00000111 -
0111.11110101
====結果是 ====
0000.00010010
然后將0000.00010010重新轉換成十進制
如何轉換成10進制?
有個公式可以用:假設有二進制數 ABC.XYZ ,轉換成10進制的值為
ABC.XYZ =A×2^2 + B×2^1 + C×2^0 + X×2^-1 + Y×2^-2 + Z×2^-3 (^ 這個是冪運算符號,這個公式適用于任何進制轉換成十進制,只需將底數替換成相應的進制就可以了)
通過這個公式,我們我們可以將二進制數的每一位對應轉換成十進制,然后相加,就得到最后的結果了。
0000.00010010 =0 + 1×2^-4 + 2^-7 =0.0703125
好了,現在很清晰了,計算機得出的最終結果是0.703125,而不是0.7!!!
似乎和計算器中0.06999999有點不一樣?
沒錯,因為我們的精度不夠:剛開始的時候,我們只取了8位二進制小數!
如果我們能以單精度23個數據位來計算的,結果是:0.06982421875
如果能以雙精度52個數據位來計算,那結果就是:0.06999999......
簡單的來說就是,由于咱們目前計算機技術的原因,這個問題是必然會出現的,而且這個問題在目前還無法從根本上解決,但可以通過某些技術手段來進行規避,例如在進行小數運算時先乘以100或者更大的數字來將其轉換為整數,在運算完成后再除以相應的數字來得到精確的結果。最后,小編發現并不只是Android手機內置的計算器會出現這個問題,例如百度的計算器也會,而有些計算器能夠得到相對精確的結果就是因為對算法進行了優化的結果。
▲百度計算器算8.03-7.96時的結果