浮點(diǎn)型數(shù)據(jù)存儲(chǔ)方式分析(轉(zhuǎn))
分類(lèi): C/C++
點(diǎn)擊(此處)折疊或打開(kāi)
- const float ESPSION = 0.000001;
- if((x-y)>=-ESPSION && (x-y)<= ESPSION)
點(diǎn)擊(此處)折疊或打開(kāi)
- typedef union test
- {
- float a;
- int i;
- char c[4];
- }Test;
- int main()
- {
- Test t;
- t.a = 5.0;
- printf("%f\n",t.a)
- printf("%d\n",t.i);
- printf("%c,%c,%c,%c\n",t.c[3],t.c[2],t.c[1],t.c[0]);
- return 0;
- }
浮點(diǎn)型變量在計(jì)算機(jī)內(nèi)存中占用4字節(jié)(Byte),即32-bit。遵循IEEE-754格式標(biāo)準(zhǔn)。一個(gè)浮點(diǎn)數(shù)由2部分組成:底數(shù)m 和 指數(shù)e。
±mantissa × 2^exponent
(注意,公式中的mantissa 和 exponent使用二進(jìn)制表示)
(具體可參看深入理解計(jì)算機(jī)系統(tǒng))
底數(shù)部分 使用2進(jìn)制數(shù)來(lái)表示此浮點(diǎn)數(shù)的實(shí)際值。
指數(shù)部分 占用8-bit的二進(jìn)制數(shù),可表示數(shù)值范圍為0-255。但是指數(shù)應(yīng)可正可負(fù),所以IEEE規(guī)定,此處算出的次方(即是來(lái)自?xún)?nèi)存存儲(chǔ)的內(nèi)容,存儲(chǔ)指數(shù))須減去127才是真正的指數(shù)(實(shí)際的指數(shù),如12.5轉(zhuǎn)換為二進(jìn)制為:1100.100=1.100100*23, 3即為實(shí)際指數(shù))。所以float的指數(shù)可從 -126到128.
底數(shù)部分實(shí)際是占用24-bit的一個(gè)值,由于其最高位始終為1,所以最高位省去不存儲(chǔ),在存儲(chǔ)中只有23-bit。到目前為止,底數(shù)部分23位加上指數(shù)部分8位 使用31位。那么前面說(shuō)過(guò),float是占用4個(gè)字節(jié)即32-bit, 那么還有一位是干嘛用的呢? 還有一位,其實(shí)就是4字節(jié)中的最高位,用來(lái)指示浮點(diǎn)數(shù)的正負(fù),當(dāng)最高位是1時(shí),為負(fù)數(shù),最高位是0時(shí),為正數(shù)。
也就是說(shuō)我們可以認(rèn)為float在小端CPU的編碼方式應(yīng)該是:
31<-------------------------------------------------0
S(1bit)| E(8bits)| M(23bits) |
即:
-----------------------------------------------------
ADDR0+3 ADDR0+2 ADDR0+1 ADDR0
SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM
-----------------------------------------------------
S: 表示浮點(diǎn)數(shù)正負(fù),1為負(fù)數(shù),0為正數(shù)。
E: 指數(shù)加上127后的值的二進(jìn)制數(shù)
M: 24-bit的底數(shù)(只存儲(chǔ)23-bit)
需要注意,浮點(diǎn)數(shù)為0時(shí),指數(shù)和底數(shù)都為0,但此前的公式不成立。因?yàn)?/span>2的0次方為1,所以,0是個(gè)特例。當(dāng)然,這個(gè)特例也不用認(rèn)為去干擾,編譯器會(huì)自動(dòng)去識(shí)別。
這樣我們就可以知道前面這個(gè)題中輸出的結(jié)果啦,從上面的分析可以知道一個(gè)float型的數(shù)的基本存儲(chǔ)方式,按照上面的實(shí)現(xiàn)可以知道5.0的存儲(chǔ)方式為如下的形式:
01000000101000000000000000000000
從上面的這個(gè)存儲(chǔ)形式我們可以得到基本的整形數(shù)值時(shí)0x40A00000。進(jìn)而也就知道了4個(gè)bytes中的數(shù)值大小。
這是充分利用了聯(lián)合體的共享內(nèi)存特性,我們改變程序如下所示:
點(diǎn)擊(此處)折疊或打開(kāi)
- #include<stdio.h>
- typedef union test
- {
- float a;
- int i;
- char c[4];
- }Test;
- int main()
- {
- Test t;
- t.a = 5.0;
- printf("%f\n",t.a);
- printf("%d\n",t.i);
- printf("%c,%c,%c,%c\n",t.c[3],t.c[2],t.c[1],t.c[0]);
- t.i = 65;
- printf("%f\n",t.a);
- printf("%d\n",t.i);
- printf("%c,%c,%c,%c\n",t.c[3],t.c[2],t.c[1],t.c[0]);
- return 0;
- }
根據(jù)上面的分析,可以比較方便的計(jì)算出結(jié)果如下所示:
當(dāng)然這只是我在X86系統(tǒng)中的輸出,在大端系統(tǒng)中會(huì)是什么結(jié)果我不得而知,具體的要參看IEEE標(biāo)準(zhǔn)。
float類(lèi)型的數(shù)據(jù)是比較復(fù)雜的問(wèn)題,我將在后面認(rèn)真研究,爭(zhēng)取早日解決各種問(wèn)題。
posted on 2013-11-11 18:42 ** 閱讀(199) 評(píng)論(0) 編輯 收藏