閱讀本文大約需要8分鐘...
問題在計算機的世界裡,可能有很多常人無法理解的事情。比如 0.1 0.2 = ?。來,告訴我你的答案。
有的朋友看到這就迫不及待的說,這麼簡單的問題,很明顯等于 0.3 啊,小學生都會算的好伐。你這是在侮辱我的智商?
好吧,我來告訴你一個打臉的事實,0.1 0.2 還真不等于 0.3 。先别急着反駁我。
打開你的任意一個浏覽器(我用chrome做演示),F12打開console控制台,輸入 console.log(0.1 0.2) 。如果你操作正确的話,你會看到以下的結果。
是不是感覺匪夷所思,what?為什麼結果是0.30000000000000004,這是神魔鬼? 難道,我這麼多年學習的數學知識,老師教的都是錯的?
别着急。其實,你的老師教的沒錯,在我們的世界中,0.1 0.2 确實是等于 0.3 的。但是,在計算機中,可就不是這麼一回事了。待我娓娓道來。
因為,我們在計算數學問題的時候,用的是十進制,計算出來結果是0.3沒問題。但是,在計算機中用的是二進制,都是由0和1來組成。這就不得不提一下,十進制轉換二進制了。
二進制轉換十進制小數轉換二進制的步驟:(以10.25為例)
1.先轉換整數部分,除2直到商為0,倒數取餘。
倒數取餘,就是1010
2.再轉換小數部分,乘2取整,直到小數部分為0.
小數部分為0,結束,即為01
因此10.25(10)轉換成二進制,結果就是 1010.01(2)
聰明的你,類比以上方法,應該可以動手去算一下十進制0.1轉成二進制是多少了。
等等,怎麼感覺進入死循環了,小數部分乘以2,一直乘不到小數部分為0
就像十進制中1/3,結果是0.3(3...)這樣的問題一樣,0.1轉成二進制時也會存在精度問題,我們需要進行取舍。
我們看一下0.1在計算機中是怎麼存儲的。對此,需要了解一下浮點數的概念。
浮點數
浮點數,顧名思義,小數點是浮動的數。千萬不要以為浮點數就是小數。因為,在js中是沒有整數和小數的概念的,其實整數也是以浮點數的形式表示的,隻是小數部分為0而已。
浮點數簡單理解,就是類似于我們十進制中的科學計數法。在計算機中一般遵循IEEE 754标準。格式如下:
因此,上邊的10.25(二進制1010.01)按照此格式表示即為 1.01001 * 2^3
對于32位浮點數來說,符号位占一位,指數位占8位,尾數占23位 對于64位浮點數來說,符号位占一位,指數位占11位,尾數占52位
IEEE 754标準注意:IEEE 754标準規定,在保存尾數M時,第一位默認是1,因此可以被舍去,隻存儲後邊的部分。例如,1.01001保存的時候,隻保存01001,等到用的時候再把1加上去。這樣,就可以節省一個位的有效數字。
指數E在存儲的時候也有些特殊。若為32位,指數占8位,則可表示的大小範圍為0-255 。如為64位,指數占11位,範圍為0-2047 。但是,指數是有正有負的,因此實際值需要在此基礎上減去一個中間數。對于32位,中間數為127,對于64位,中間數為1023 。
還是以1.01001 * 2^3 為例,若為32位浮點數,則需要保存成 3 127 = 130,即二進制的10000010,若為64位浮點數,則保存成 3 1023 = 1026 ,即二進制的10000000010。
計算步驟好了。巴拉巴拉了這麼多。終于,要進入我們今天的正題了。
我們看一下 0.1 在計算機中是怎麼用 IEEE 754标準存儲的。
十進制0.1轉為二進制為0.0001100110011(0011循環),即 1.100110011(0011)*2^-4,因此符号位為0,尾數1.100110011(0011),階碼為 -4,實際存儲為 -4 1023 = 1019 的二進制 1111111011
十進制0.2轉為二進制為0.001100110011(0011循環),即 1.100110011(0011)*2^-3 ,存儲時,符号位為0,尾數 1.100110011(0011),階碼為-3,實際存儲為 -3 1023 = 1020 的二進制 1111111100。
接下來,計算 0.1 0.2 。
浮點數進行計算時,需要對階。即把兩個數的階碼設置為一樣的值,然後再計算尾數部分。其實對階很好理解,就和我們十進制科學記數法加法一個道理,先把指數部分化成一樣,再計算尾數。
另外,需要注意一下,對階時需要小階對大階。因為,這樣相當于,小階指數乘以倍數,尾數部分相對應的除以倍數,在二進制中即右移倍數位。這樣,不會影響到尾數的高位,隻會移出低位,損失相對較少的精度。
因此,0.1的階碼為 -4 , 需要對階為 0.2的階碼 -3 。尾數部分整體右移一位。
然後進行尾數部分相加
可以看到,産生了進位。因此,階碼需要 1,即為 -2,尾數部分進行低位四舍五入處理。因尾數最低位為1,需要進位。所以存儲為:
最後把二進制轉換為十進制,
問題總結1.在十進制轉換為二進制的過程中,會産生精度的損失。
2.二進制浮點數進行對階運算時,也會産生精度的損失。
因此,最終結果才産生了偏差。
看完的小夥伴,現在應該能理解,為什麼0.1 0.2 ≠ 0.3 這個問題了吧。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!