這是"IEEE754標(biāo)準(zhǔn)系列"的第二篇文章. 主要討論32位浮點數(shù) (或者說float類型) 的取值范圍到底是如何計算出來的.
本章主要參考自 IEEE754 wiki
一. wiki中, 32位浮點數(shù)的取值范圍
這里先直接給出維基上的取值范圍:
可見float類型, 或者說32位浮點數(shù)的取值范圍是:
或者說是:
直觀表示的話就是:
[-340000000000000000000000000000000000000, -0.0000000000000000000000000000000000000118] ∪ [0.0000000000000000000000000000000000000118, 340000000000000000000000000000000000000]
二. 前置概念
在詳細(xì)介紹這個范圍是怎么計算出來的之前, 我們必須先了解一些概念.只有了解了這些概念, 才能真正的理解浮點數(shù)的取值范圍是如何計算出來的.
而且此處假定你已經(jīng)對IEEE754浮點數(shù)在內(nèi)存中的存儲方式有所了解, 還不了解的話也可以參考本系列的第一篇文章.
那這就開始吧
概念1: normal number(規(guī)格數(shù))? & subnormal number(非規(guī)格數(shù))
根據(jù)IEEE754的規(guī)定, 按照尾數(shù)位隱藏的整數(shù)部分是 1. 還是0. 可以將浮點數(shù)劃分為兩類: normal number(規(guī)格數(shù))? 和 subnormal number(非規(guī)格數(shù))
下面以32位浮點數(shù)為例來解釋這些概念.
normal number(規(guī)格數(shù))
就是尾數(shù)位隱藏的整數(shù)部分是1.的數(shù), 這種數(shù)叫做normal number, 可以理解為"正常的數(shù)"
一般來說, 我們遇到的都是normal number
舉例: 20.5在內(nèi)存中表示為: 0? 1000 0011? 0100 1000 0000 0000 000
其中尾數(shù)部分(即上面的加粗部分), 去掉后面補(bǔ)的零之后為: 01001
但事實上, 真實的尾數(shù)部分應(yīng)該是: 1.01001, 即前面省略了整數(shù)部分1.
subnormal number(非規(guī)格數(shù))
尾數(shù)位隱藏的整數(shù)部分為0.的數(shù), 叫做subnormal number, 也叫作denormal number, 可以理解為"低于正常數(shù)的數(shù)"
引入subnormal number這個概念, 是為了在浮點數(shù)下溢時, 可以逐位的損失精度, 以盡可能精確的表達(dá)0附近的極小數(shù), 之后的章節(jié)會具體講解.
為了表示subnormal number, IEEE754規(guī)定: 如果將指數(shù)位全部填充為0, 則表示這個數(shù)是個subnormal number
舉例: 以32位浮點數(shù)為例, 當(dāng)你看到類似于 * 00000000 *********************** 這樣內(nèi)存狀態(tài)的數(shù)時, (即指數(shù)位全部為0的數(shù)), 就應(yīng)該知道, 這是個subnormal number, 此時這個數(shù)的尾數(shù)位隱藏的整數(shù)不是1.? 而是0.
概念2: non-number(特殊數(shù))
和subnormal number類似, IEEE754對于指數(shù)位全為1的狀態(tài)也做了特殊規(guī)定:
當(dāng)指數(shù)位全部被1填充, 即指數(shù)位表示的值為255時, 用于表示這個浮點數(shù)處在一種非正常數(shù)(non-number)的狀態(tài): 即這個數(shù)可能是±infinity或NaN.
注: Infinity和NaN是兩個特殊數(shù), 分別表示無窮和Not a Number. 我們后文還會詳細(xì)討論這兩個特殊數(shù)
The biased-exponent field is filled with all 1 bits to indicate either infinity or an invalid result of a computation.
所以: 當(dāng)你看到類似于 * 11111111 *********************** 這樣內(nèi)存狀態(tài)的數(shù)時, (即指數(shù)位全部為1的數(shù)), 就應(yīng)該知道, 這是個non-number, 它用于表示特殊數(shù).
三. 計算方法
在了解了上面兩個概念之后, 再看計算方法就很簡單了.
如上所述, IEEE754規(guī)定, 當(dāng)指數(shù)位全部為0或者全部為1時, 用于表示兩種特殊狀態(tài)的數(shù): subnormal number 和 non-number, 所以現(xiàn)在可以得到如下示意圖, 以32位單精度浮點數(shù)為例:
這就是理解單精度浮點數(shù)取值范圍的關(guān)鍵: 當(dāng)我們討論浮點數(shù)的取值范圍時, 實際上討論的是: normal number (上圖中綠色部分)的范圍.
可以看出, 32位浮點數(shù)的指數(shù)部分其實是無法取到-127和128的, 因為:
用于表示-127的0000 0000被用來表示subnormal number了,
而用于表示128的1111 1111被用來表示non-number了.
所以實際上32位浮點數(shù)的指數(shù)部分只能取到只能取到[-126, 127]
再來看看尾數(shù): 對于normal number, 尾數(shù)前隱藏的整數(shù)部分始終保持為1.
所以尾數(shù)(含隱藏的整數(shù)部分)所表示的值的范圍其實是 [1.00...00, 1.11...11],
這個二進(jìn)制數(shù), 約等于十進(jìn)制的[1, 2), 因為1.11..11非常逼近十進(jìn)制的2
好啦, 現(xiàn)在我們知道, 對于32位flaot而言: 尾數(shù)(含隱藏的整數(shù)部分)的可取值為: [1 ,2), 指數(shù)位可取值[-126, 127], 且浮點數(shù)可正可負(fù), 根據(jù)運(yùn)算規(guī)則, 就不難算出32位float的取值范圍了:
取值范圍
注意開閉區(qū)間哦
然后為了看著順眼, 我們把上式的以2為底, 替換為以10為底:
↑ 轉(zhuǎn)換后小數(shù)位太長了, 所以這里寫成了省略號的形式: 3.402823669...
從上面這個集合中, 取一個更容易表示的子集, 就是我們常見的32位float的取值范圍了:
↑ 注意, 上面這個集合其實是32位float取值范圍的子集, 不過和真正的取值范圍也沒有差太多, 表示起來也更簡潔, 沒有冗長的小數(shù)位, 還能寫成閉區(qū)間的形式...所以在各種資料中, 我們澄辏看到的取值范圍就是上面這個.
↑ 之所以能寫成閉區(qū)間的形式, 就是因為它只是真正取值范圍的一個子集. 這里特意說明一下, 防止有的同學(xué)對這里的閉區(qū)間感到困惑.
四: 補(bǔ)充
下面是 32位單精度浮點數(shù)的取值范圍示意圖, 可以參照此圖更好的理解一下前文內(nèi)容
下圖中, x軸代表以2為底的n次冪(即內(nèi)存中的指數(shù)部分), y軸代表尾數(shù)(含隱藏的整數(shù)部分1.)
坐標(biāo)系中任意一點(x, y)就代表一個浮點數(shù),
這一點到x軸, y軸所圍成的矩形的面積(即上圖中橙色區(qū)域的面積), 就是這個浮點數(shù)的值 (即浮點數(shù)的值 = 尾數(shù)(含隱藏的整數(shù)部分) * 以2為底的n次冪)
上圖中:
藍(lán)色部分: 表示normal number的取值范圍, 即, normal number類型的浮點數(shù)對應(yīng)的坐標(biāo)點只能出現(xiàn)在坐標(biāo)系中的藍(lán)色區(qū)域.
坐標(biāo)點: 一個坐標(biāo)點對應(yīng)一個浮點數(shù)
橙色部分的面積: 表示該浮點數(shù)的值.
這就是32位浮點數(shù)取值范圍的計算方法.
下一章將詳細(xì)介紹為什么說32位浮點數(shù)的精度是"7位有效數(shù)", 這個7是怎么計算出來的, 下一章也將會是整個系列中最有難度, 最重要的一章.
那下一章再見吧~