淺談浮點數
時間:2017-01-06作者:華清遠(yuan)見
浮(fu)點型變量在計(ji)算(suan)機內存中占用4字(zi)節(jie)(Byte),即(ji)32-bit。遵循IEEE-754格(ge)式標準。 一個(ge)浮點(dian)數(shu)由2部分組成:底數(shu)m 和 指數(shu)e。 ±mantissa × 2exponent(注意,公式中的mantissa 和 exponent使用二進制表示) 底數部分 使用2進制數來表示此浮點數的(de)實際值。 指數(shu)(shu)(shu)部分 占(zhan)用8-bit的(de)(de)二進制數(shu)(shu)(shu),可表示數(shu)(shu)(shu)值(zhi)范圍為0-255。 但是(shi)指數(shu)(shu)(shu)應可正可負(fu),所以(yi)IEEE規定, 此處(chu)算出的(de)(de)次方須減去127才(cai)是(shi)真正的(de)(de)指數(shu)(shu)(shu)。所以(yi)float的(de)(de)指數(shu)(shu)(shu)可從 -126到128。 底數(shu)部分實際是(shi)占用(yong)24-bit的一(yi)個值,由于其高位始終為(wei) 1 ,所以高位省(sheng)去(qu)不存儲(chu),在存儲(chu)中只(zhi)有23-bit。 到(dao)目前(qian)為(wei)止, 底數(shu)(shu)部分 23位(wei) 加上指數(shu)(shu)部分 8位(wei) 使用(yong)了31位(wei)。那(nei)么(me)前(qian)面說過,float是占用(yong)4個字節(jie)即(ji) 32-bit,那(nei)么(me)還(huan)有(you)一位(wei)是干嘛(ma)用(yong)的呢? 還(huan)有(you)一位(wei),其實(shi)就是4字節(jie)中的高(gao)(gao)位(wei),用(yong)來指示浮點(dian)數(shu)(shu)的正負,當(dang)高(gao)(gao)位(wei)是1時(shi),為(wei)負數(shu)(shu),高(gao)(gao)位(wei)是0時(shi),為(wei)正數(shu)(shu)。 浮點(dian)數據(ju)就是按下表的(de)格(ge)式存(cun)儲在(zai)4個字節(jie)中:
Address+0 Address+1 Address+2 Address+3 注意:這里(li)有個(ge)特例,浮點數(shu) 為(wei)(wei)(wei)0時,指數(shu)和底數(shu)都為(wei)(wei)(wei)0,但(dan)此前的公式不(bu)成立。因為(wei)(wei)(wei)2的0次方為(wei)(wei)(wei)1,所以0是(shi)個(ge)特例。當然(ran),這個(ge)特例也不(bu)用認為(wei)(wei)(wei)去(qu)(qu)干擾,編譯器(qi)會自動去(qu)(qu)識別(bie)。 通過(guo)上面(mian)的(de)格式(shi),我們下面(mian)舉(ju)例看下-12.5在計算機(ji)中存儲的(de)具體數據(ju):
Address+0 Address+1 Address+2 Address+3 接下(xia)來我們(men)驗證下(xia)上面的數(shu)據(ju)表示的到底是不(bu)是-12.5,從而(er)也看下(xia)它的轉換過程。 由于浮點(dian)數不是(shi)以直(zhi)接格式存(cun)儲,他有幾部分(fen)組成,所(suo)以要轉(zhuan)換浮點(dian)數,首先要把各部分(fen)的(de)值分(fen)離出來。
Address+0 Address+1 Address+2 Address+3 這里(li),在底數左邊省略存(cun)儲了一個1,使用實際底數表示為 1.10010000000000000000000 。 現在,我(wo)們通過指(zhi)數(shu)(shu)(shu)部分(fen)(fen)E的(de)值來調整底數(shu)(shu)(shu)部分(fen)(fen)M的(de)值。調整方法為(wei)(wei):如果(guo)指(zhi)數(shu)(shu)(shu)E為(wei)(wei)負數(shu)(shu)(shu),底數(shu)(shu)(shu)的(de)小(xiao)(xiao)數(shu)(shu)(shu)點向(xiang)(xiang)左移,如果(guo)指(zhi)數(shu)(shu)(shu)E為(wei)(wei)正數(shu)(shu)(shu),底數(shu)(shu)(shu)的(de)小(xiao)(xiao)數(shu)(shu)(shu)點向(xiang)(xiang)右移。小(xiao)(xiao)數(shu)(shu)(shu)點移動的(de)位數(shu)(shu)(shu)由指(zhi)數(shu)(shu)(shu)E的(de)絕對值決定(ding)。 這(zhe)里,E為(wei)正3,使用向(xiang)右移3為(wei)即得:1100.10000000000000000000。 至(zhi)次,這(zhe)個結(jie)果就(jiu)是12.5的二進制(zhi)浮點數,將(jiang)他(ta)換算成10進制(zhi)數就(jiu)看(kan)到12.5了,如(ru)何轉換,看(kan)下面: 小(xiao)數點左邊的(de)1100 表示為 (1 × 23) + (1 × 22) + (0 × 21) + (0 × 20), 其結果為 12 。 小數點(dian)右(you)邊的 .100… 表(biao)示為 (1 × 2-1) + (0 × 2-2) + (0 × 2-3) + ... ,其結(jie)果為.5 。 以上(shang)二值的(de)和為12.5, 由于(yu)S 為1,使用為負數,即(ji)-12.5 。 所以,16進制 0XC1480000 是浮點數 -12.5 。 上面是如何(he)將計(ji)算機存儲中的(de)(de)二進制數如何(he)轉(zhuan)換成(cheng)實際浮(fu)點數,下(xia)面看下(xia)如何(he)將一浮(fu)點數裝換成(cheng)計(ji)算機存儲格式中的(de)(de)二進制數。 舉(ju)例將17.625換(huan)算成 float型。 首先,將17.625換(huan)算成(cheng)二進制位(wei):10001.101 ( 0.625 = 0.5+0.125, 0.5即 1/2, 0.125即 1/8 如果(guo) 不會(hui)將小數(shu)部分轉(zhuan)換(huan)成(cheng)二進制,請(qing)參考其他書籍。) 再將 10001.101 向右(you)移,直到小數(shu)點(dian)前只剩一位(wei) 成(cheng)了(le) 1.0001101 x 2的(de)4次方(fang) (因為右(you)移了(le)4位(wei))。此時 我們的(de)底(di)數(shu)M和指數(shu)E就(jiu)出(chu)來了(le): 底數(shu)(shu)部分M,因為小(xiao)數(shu)(shu)點(dian)前(qian)必為1,所(suo)以(yi)(yi)IEEE規定只記錄小(xiao)數(shu)(shu)點(dian)后的就好,所(suo)以(yi)(yi)此處底數(shu)(shu)為 0001101 。 指數部分E,實際為4,但(dan)須加上127,固為131,即二進制數 10000011 符號(hao)部分S,由于(yu)是正(zheng)數(shu),所(suo)以S為0。 綜上所述,17.625的 float 存儲(chu)格(ge)式就是:0 10000011 00011010000000000000000 轉(zhuan)換成16進制:0x41 8D 00 00 所(suo)以,一看,還是占用了4個字節。 接下來看存儲:
Float數據結構:
Double數據結構: Exp在公式中是2的冪(mi),接近零(ling)的小數(shu)的描述應為(wei)有符號數(shu),有符號數(shu)的表示可以為(wei)符號位+數(shu)字位、補(bu)數(shu)等(deng),IEEE754采(cai)用的是偏移法,不作過多(duo)解釋。 對(dui)Float偏移(yi)量(liang)為(wei)0x7F(127)、Double偏移(yi)量(liang)為(wei)0x3FF(1023)。 Frac便是有效位數,
注釋 浮點值 S Exp Frac 數學值 首先舉例求Float_Max正(zheng)正(zheng)規數:
Exp =0xFE = 254; 其(qi)它的可自己求(qiu)。 所以float 型的冪是38,Double的冪應該是308。
相關資訊
發表評論
|