爲什麼float類型30000000.0f+3.0f的結果仍然是30000000.0f

1. 首先看問題結果

是不是結果還是 30000000.0f 而不是 30000003.0f

 

2. 分析原因

這是一個典型的大數喫小數問題,原因需要從浮點數的計算機實現說起

對於float,是4字節(強調下我這裏講的都是32位浮點數,其它位思想同樣適用),共32個bit,那麼怎麼用這32位來表示float

首先最容易想到的是  浮點數的每位十進制數用4bit來表示,比如 999999.99 這樣每個9用1001表示,那麼在32bit上的佈局是下面這樣:  100110011001100110011001.10011001   這樣的表示數據範圍是 000000.00 ~ 999999.99 共大概1億個數字,這種把小數點固定的方法就是 “定點小數”,這樣表達簡單易懂,但是有個缺點就是,明明32bit可以最多表示42億個數字,現在只能表示1億,太浪費了。

 

還有一個就是 “浮點小數” ,顧名思義,就是小數點會浮動,比如 99.5 你可以表示成 9.995 x 10^1,也可以

表示成0.9995 x 10^2, 小數點可以浮動必然需要引入指數,這就是我們學數學的時候說的科學計數法,但是這是10進制,二進制數同樣適用,只是科學計數法的底數是2而已。對於浮點數的二進制表示 常規的是 IEEE-754標準(強調下我下面講都是IEEE-754標準),回頭我打算再寫一篇博客專門介紹一下這個標準(可以到時候留意下我的博客更新),現在我們只需要知道,這套標準定義下的浮點數是把32位bit位,劃分爲3部分:

對於 30000000.0f,二進制浮點數表示如下: 

A = 0 10010111 11001001110000111000000  (依次是符號位1位  指數位8位  數字位23位)

對於 3.0f,二進制浮點數表示如下: 

B = 0 10000000 10000000000000000000000  (依次是符號位1位  指數位8位  數字位23位)

轉換工具可參考 : https://www.h-schmidt.net/FloatConverter/IEEE754.html

 

現在就是 A + B  ,其中A和B的指數位和數字位均不同,CPU此時會把 A和B的指數位統一(向大數A的指數靠攏),這樣只要 加 A和B的數字位就可以了,A和B的指數位相差23位,如果B的指數位要跟A一致,那麼B的數字位就要整體向右移動23位,正好把B的數字部分

10000000000000000000000   第一個1溢出了,這就是爲什麼  30000000.0f + 3.0f 結果還是 30000000.0f的原因。

 

特別提醒下,IEEE754 的指數位表示的不是真實的指數值,而是有個映射關係:1~254(bit表示值,0和255有另外的作用) 映射到 -126~127(指數表示的真實值) 這 254 個有正有負的數上。如果我們把 32bit劃分的3個部分分別表示爲 s(符號位),e(指數位),f(數字位),那麼沒有參與映射的0和255有如下的作用:

下篇我在講IEEE754標準的博客裏會把這個也交代清楚

 

 

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