準確詳解:C/C++ float、double數據類型的表示範圍及精度

 

 今天覆習C++遇到了float、double數據類型的表示範圍及精度問題,花費了一些時間重新梳理了一遍,鑑於網上很多文章寫的並不清晰,並且有不少疏漏錯誤之處,特結合個人理解仔細整理如下。

  要弄清楚這個問題,首先要搞清楚浮點數在內存中的存儲方式。浮點數,區別於定點數,指的是小數點位不確定的的數據類型,其原理是將一個浮點數a用兩個數m(尾數)和e(指數)來表示:a = m × b^e。其中的b爲選取的基數。科學計數法就是一種特殊形式的浮點數。

  在計算機二進制表示中,浮點數採用2作爲基數,規定尾數的範圍爲1.0~2.0之間。

 以float類型爲例,根據最廣泛採用的IEEE754標準規定,float數據類型長度爲32位,其中最高位爲符號位,中間8位爲指數位,最後23位作爲尾數位。

  最高位符號位通過0/1來區分正負,0正1負;指數位則規定採用移碼的形式存儲,這樣可以保證指數部分爲無符號數,方便比較大小。移碼錶示法是在數X上增加一個偏移量來定義的,如果機器字長爲n,規定偏移量爲2^(n-1),對於8位補碼-128~127,可得到對應的階碼錶示爲0~255,其中全0和全1分別用來表示0和無窮大,故規定1~254用來表示規範數字,即對應指數範圍從-126127;尾數部分統一規定爲1.0-2.0之間,最高位必然爲1,故可以省略,所以尾數部分從小數點後算起,最小可以取到1,最大則取到二進制1.1...1(小數點後23位),即取到2-2^-23,可近似約等於2。故得到float絕對值的最大值取到2^127*(2-2^-23)約等於2^128=3.4E+38。加上符號之後可得float表示範圍爲(-3.4E+38)~(3.4E+38)。當然實際是取不到的,開區間。絕對值最小則可以取到2^-127*1,即爲1.175E-38。

接下來解釋精度。由於尾數部分位數是固定的小數點後23位,23位所能表示的最大數是2^23−1=8388607,所以十進制的尾數部分最大數值是8388607,也就是說尾數數值超過這個值之後,float將無法精確表示,所以float最多能表示小於8388607的小數點後7位,但絕對能保證的爲6位,也即float的十進制的精度爲爲6~7位。

double數據類型的推算過程和上述同理,唯一的區別在於尾數由23位擴展到52位,階碼由8位增加到了11位,計算方法不變。所以double的階碼(移碼錶示)爲1~2046,偏移量爲1023,故指數範圍爲-1022~1023,得表示範圍爲(2^1023*2)~(-2^1023*2)即爲-1.7E+308~1.7E+308,絕對值最小可以取到2^-1022,精度則爲2^52-1=4503599627370495,爲16位。所以精度最高位16位,一定可以保證15位。

 

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