您好,登錄后才能下訂單哦!
首先,將10進(jìn)制的小數(shù)0.1轉(zhuǎn)換為二進(jìn)制,方法如下:
0.1*2==0.2 取0.2的整數(shù)部分, 結(jié)果為0.0
0.2*2==0.4 取0.4的整數(shù)部分, 結(jié)果為0.00
0.4*2==0.8 取0.8的整數(shù)部分, 結(jié)果為0.000
0.8*2==1.6 取1.6的整數(shù)部分, 結(jié)果為0.0001
0.6*2==1.2 取1.6的整數(shù)部分, 結(jié)果為0.00011
0.2*2==0.4 取0.4的整數(shù)部分, 結(jié)果為0.000110
最后這一步開始循環(huán),因此0.1的二進(jìn)制為數(shù)為: 0.0001100110011...是一個無限循環(huán)小數(shù),二進(jìn)制數(shù)據(jù)無法精確表示.
當(dāng)然,有些小數(shù)是不循環(huán)的,可以用二進(jìn)制數(shù)據(jù)精確表示,如10進(jìn)制的0.5轉(zhuǎn)換為轉(zhuǎn)換為二進(jìn)制:
0.5*2=1.0 取1.0的整數(shù)部分, 結(jié)果為0.1
0.0*2=0.0 取0.0的整數(shù)部分, 結(jié)果為0.10
再進(jìn)行運(yùn)算下去,可以認(rèn)為0.5的二進(jìn)制數(shù)據(jù)為0.10000...,也就是1.0,不是循環(huán)小數(shù).
可見,按照上面的運(yùn)算方法,運(yùn)算結(jié)果不為0且循環(huán)的時候則是無限循環(huán)小數(shù),運(yùn)算結(jié)果為0,則不是循序小數(shù).
下面是幾個二進(jìn)制小數(shù)和10進(jìn)制小數(shù)對應(yīng)關(guān)系:
0.1 == 0*2^1 + 1*2^-1 == 1/2 == 0.5 == 0*10^1 + 5*10^-1
0.01 == 0*2^1 + 0*2^-1 + 1*2^-2 == 0.25 == 0*10^1 + 2*10^-1 + 5*10^-2
0.001 == 0*2^1 + 0*2^-1 + 0*2^-2 + 1*2^-3 == 1/8 == 0.125 == 0*10^1 + 1*10^-1 + 2*10^-2 + 5*10^-3
0.0001 == 0*2^1 + 0*2^-1 + 0*2^-2 + 0*2^-3 + 1*10^-4 == 1*2^-4 == 1/16 == 0.0625 == 0*10^1 + 0*10^-1 + 6*10^-2 + 2*10^-3 + 5*10^-4
... ...
從這幾個對應(yīng)關(guān)系可以看出二進(jìn)制和十進(jìn)制本質(zhì)是一樣的,用科學(xué)計數(shù)法來表示: 1*2^-m+...1*2^-n
那么,小數(shù)如何在內(nèi)存中存儲呢? 以float fpi=0.1415926為例說明
第一步: 將十進(jìn)制的0.141593轉(zhuǎn)換為二進(jìn)制數(shù)為: 0.001000011111101101001101000100...已經(jīng)舍去了一部分
第二步: 將第一步的二進(jìn)制小數(shù)點(diǎn)向右移動3位: 1.000011111101101001101000100 * 2^-3
第三步: 計算階碼,提取第二步中的指數(shù)-3,然后計算階碼: -3 + 127 == 124,124(小于127,說明是一個負(fù)數(shù))的二進(jìn)制數(shù)為: 1111 100,用8位表示就是0 1111 100
第四步: 獲取尾數(shù),將第二步中的1.000011111101101001101000100-1=000011111101101001101000100
第五步: 將第四步的獲取的結(jié)果舍掉多余的部分,僅保留高23位: 0000111111011010011010
第六步: 將第3,5步的結(jié)果拼接到一塊,并加上符號位(正號0): (符號)0 (階碼)01111100 (尾數(shù))0000111111011010011010
浮點(diǎn)數(shù)0.1415926在內(nèi)存中存儲的二進(jìn)制數(shù)為: 0 01111100 0000111111011010011010
如果小數(shù)帶整數(shù)部分,如3.1415926,轉(zhuǎn)換過程差不過:
1.分別將整數(shù)和小數(shù)轉(zhuǎn)換為二進(jìn)制數(shù): 011.001000011111101101001101000100
2.將第1步中的二進(jìn)制數(shù)小數(shù)點(diǎn)向左移動1位: 1.1001000011111101101001101000100
3.計算階碼,提取第2步中的指數(shù)+2,然后計算階碼: +2 + 127 == 128,128(大于127,說明是一個正數(shù))的二進(jìn)制數(shù)為: 10000000,共8位(階碼是一個正數(shù),可省略符號位)
4.獲取尾數(shù),將第2步中的1.1001000011111101101001101000100-1=1001000011111101101001101000100
5.將第4步的獲取的結(jié)果舍掉多余的部分,僅保留高23位: 10010010000111111011010
6.將第3,5步的結(jié)果拼接到一塊,并加上符號位(正號0): (符號)0 (階碼)10000001 (尾數(shù))10010010000111111011010
浮點(diǎn)數(shù)3.1415926在內(nèi)存中存儲的二進(jìn)制數(shù)為: 0 10000000 10010010000111111011010
通過上面的例子,說明一下浮點(diǎn)數(shù)如何在內(nèi)存中存儲
C/C++編譯器標(biāo)準(zhǔn)都遵照IEEE制定的浮點(diǎn)數(shù)表示法來進(jìn)行float/double運(yùn)算,將浮點(diǎn)數(shù)轉(zhuǎn)換為二進(jìn)制的科學(xué)計數(shù)法: V = (-1)s * M * 2^E
(-1)s 表示符號位,當(dāng)s=0,V為正數(shù);當(dāng)s=1,V為負(fù)數(shù).
M表示有效數(shù)字,1<=M<2.
E表示指數(shù)位
float和double類型,s,M,E的位數(shù)為:
符號位s 階碼M 尾數(shù)M 長度
float(32bits) 1 8 23
double(64bits) 1 11 52
尾數(shù)M的的規(guī)則
1.必須保證1≤M<2,也就是說,M可以寫成1.xxxxxx的形式,其中xxxxxx表示小數(shù)部分.在計算機(jī)內(nèi)部保存M時,默認(rèn)這個數(shù)的第一位總是1,因此可以被舍去,只保存后面的xxxxxx部分
等到讀取的時候,再把第一位的1加上去.這樣做的好處是節(jié)省1位有效數(shù)字.以32位浮點(diǎn)數(shù)為例,留給 M只有23位,將第一位的1舍去以后,等于可以保存24位有效數(shù)字.
2.尾數(shù)必須用原碼表示,無論浮點(diǎn)數(shù)是正數(shù)還是負(fù)數(shù).
注:
1985年IEEE(Institute of Electrical and Electronics Engineers)提出了IEEE754標(biāo)準(zhǔn).該標(biāo)準(zhǔn)規(guī)定基數(shù)為2,階碼E用移碼表示,尾數(shù)M用原碼表示,根據(jù)二進(jìn)制的規(guī)格化方法,最高數(shù)字位總是1,該標(biāo)準(zhǔn)將這個1缺省存儲,使得尾數(shù)表示范圍比實際存儲的多一位.
階碼的規(guī)則
階碼的本質(zhì)上是無符號整數(shù)(float 8位;double 11位),但它仍然可以表示負(fù)數(shù),其規(guī)則為:
對于float來說,階碼=E-127.
對于double來說,階碼=E-1023.
這樣,如果E為正數(shù),則階碼>127; 如果E為負(fù)數(shù),則階碼<127. 然后,指數(shù)E還可以再分成三種情況:
(1)E不全為0或不全為1.這時,浮點(diǎn)數(shù)就采用上面的規(guī)則表示,即指數(shù)E的計算值減去127(或1023),得到真實 值,再將有效數(shù)字M前加上第一位的1.
(2)E全為0.這時,浮點(diǎn)數(shù)的指數(shù)E等于1-127(或者1-1023),有效數(shù)字M不再加上第一位的1,而是還原為 0.xxxxxx的小數(shù).這樣做是為了表示±0,以及接近于0的很小的數(shù)字.
(3)E全為1.這時,如果有效數(shù)字M全為0,表示±無窮大(正負(fù)取決于符號位s);如果有效數(shù)字M不全為0,表示 這個數(shù)不是一個數(shù)(NaN).
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。