浮點(diǎn)數(shù)的計(jì)算機(jī)不計(jì)算機(jī)表計(jì)算機(jī)表示(IEEE 754),由 UCB 數(shù)學(xué)教授 William Kahan 主要起草。想過(guò)小數(shù)后者也因其卓越貢獻(xiàn)于1989年獲得圖靈獎(jiǎng)。計(jì)算機(jī)不計(jì)算機(jī)表計(jì)算機(jī)組成原理與匯編語(yǔ)言這兩門(mén)課均對(duì)該內(nèi)容有所講解。想過(guò)小數(shù)與課程中直接拋出公式與概念不同,計(jì)算機(jī)不計(jì)算機(jī)表我想首先與各位探討"科學(xué)計(jì)數(shù)法"這個(gè)概念,進(jìn)而討論設(shè)計(jì)二進(jìn)制的科學(xué)計(jì)數(shù)法需要涉及到哪些元素。接著,我們討論如何在內(nèi)存上表達(dá)這個(gè)方案。最后討論計(jì)算機(jī)的具體實(shí)現(xiàn)。
科學(xué)計(jì)數(shù)法
我們都了解科學(xué)計(jì)數(shù)法。科學(xué)計(jì)數(shù)法的精妙之處在于,其將"量級(jí)"與"數(shù)值"兩個(gè)信息拆分,讓使用者對(duì)這兩個(gè)信息更加明確。
如上,我們可以將任何有理數(shù)拆分成 的形式。值得注意的是:
的取值范圍是 一定是一個(gè)整數(shù)
對(duì)于任何有理數(shù),我們都可以用兩個(gè)范圍狹小(規(guī)則明確)的數(shù)字 B 與 C 來(lái)表示。
此外,我們知道,十進(jìn)制只不過(guò)是記錄數(shù)字大小的一種方式而已。歷史上出現(xiàn)過(guò)的二進(jìn)制、三進(jìn)制、二十進(jìn)制,都可以毫無(wú)障礙地表示數(shù)字,并且還有其獨(dú)具的數(shù)學(xué)特性。
那么,二進(jìn)制可以用科學(xué)計(jì)數(shù)法表示嗎?答案當(dāng)然是肯定的。
二進(jìn)制的科學(xué)計(jì)數(shù)法
注意,這里下標(biāo)2,代表這個(gè)數(shù)是二進(jìn)制。同理, 對(duì)應(yīng)十進(jìn)制中的數(shù)字 。
通過(guò)觀察十進(jìn)制的科學(xué)計(jì)數(shù)法形式,對(duì)于二進(jìn)制,我們自然可以做出如下約定:
的取值范圍是 一定是一個(gè)整數(shù)
這里我們補(bǔ)充說(shuō)明一下,二進(jìn)制的小數(shù)是什么樣的。對(duì)于 這個(gè)十進(jìn)制數(shù),如果要將其轉(zhuǎn)換為二進(jìn)制:
將其整數(shù)部分與小樹(shù)部分分開(kāi); 對(duì)于整數(shù)部分 5
,我們使用"不斷除以2取余數(shù)"的方法,得到101
;對(duì)于小數(shù)部分 .25
,我們使用"不斷乘以2取整數(shù)"的方法,得到.01
。
關(guān)于進(jìn)制轉(zhuǎn)換的具體方法與背后的數(shù)學(xué)原理,我寫(xiě)過(guò)一篇文章進(jìn)行討論,見(jiàn)這里:十進(jìn)制轉(zhuǎn)二進(jìn)制 / 八進(jìn)制 / 十六進(jìn)制的手算方法,及其數(shù)學(xué)原理的通俗解釋。
這里,我們只需要明確,二進(jìn)制是存在小數(shù)形式的,且可以表示一切十進(jìn)制可表示的數(shù)(的近似)。
計(jì)算機(jī)如何記錄二進(jìn)制的科學(xué)計(jì)數(shù)法
接著,我們步入正題:只會(huì)表示0/1的計(jì)算機(jī),如何記錄并表達(dá)浮點(diǎn)數(shù)呢?
給一個(gè)32位的空間,如果不做任何約束,我們只能將其理解為一個(gè)整數(shù),并且其取值范圍為 。
這是因?yàn)椋?jì)算機(jī)只能記錄 0 和 1 這兩個(gè)信息,并不能直接記錄小數(shù)點(diǎn)點(diǎn)在哪里。因此,我們需要設(shè)置一定規(guī)則,取出一定位,用于表示小數(shù)點(diǎn)點(diǎn)在哪里。這必將犧牲一定的精度與取值范圍。
因此,我們將這 32 位空間分為三部分:
第一部分,用于表示 精度
,即這個(gè)數(shù)字值是多少,對(duì)應(yīng)上面的B;第二部分,用于表示 小數(shù)點(diǎn)
,即量級(jí),對(duì)應(yīng)上面的C;第三部分,用于表示 正負(fù)
,只需要使用1位。
在 IEEE 754 中,我們分別將上述一、二、三部分叫做尾數(shù)M
,階碼E
,符號(hào)s
。于是我們有了二進(jìn)制的表達(dá)式:
為了表示盡可能多的、常用的小數(shù),我們有如下需求:
對(duì)于符號(hào)位 s ,如果該位上是 0 ,則為正數(shù);為 1 ,則為負(fù)數(shù)。 對(duì)于尾數(shù) M ,其取值范圍為 ; 對(duì)于階碼 E ,其為一個(gè)整數(shù),并且取值范圍應(yīng)該包含負(fù)數(shù)、0、正數(shù)。
可以注意到,對(duì)于 M 、 E ,我們并不能直接用二進(jìn)制表示,還需要設(shè)定一定規(guī)則。
尾數(shù) M
假設(shè)尾數(shù) M 一共有 f 位,則 f 可表示的整數(shù)取值范圍為 ,我們稱 f 直接對(duì)應(yīng)的非負(fù)整數(shù)為 C 。為了將其投影到 ,我們做出如下變換:
解碼 E
假設(shè)解碼 E 一共有 e 位,則 e 可表示的整數(shù)取值范圍為 ,我們稱 e 直接對(duì)應(yīng)的非負(fù)整數(shù)為 Exp 。我們希望 E 可以取到負(fù)數(shù),因此做出如下變換:
這樣,我們的 E 取值范圍就來(lái)到了 。
總結(jié)
有了如上設(shè)計(jì)的規(guī)則,我們便知曉了計(jì)算機(jī)記錄浮點(diǎn)數(shù)的方式,以及轉(zhuǎn)換流程。以下圖為例。
知識(shí)點(diǎn)與例題
上面我們討論了 IEEE 754 的思想,但是并不嚴(yán)謹(jǐn),比如:
正負(fù)無(wú)窮該怎么表達(dá)? 如此表示會(huì)不會(huì)造成空間的浪費(fèi)? ...
因此,我們從數(shù)學(xué)上嚴(yán)謹(jǐn)?shù)赜懻撘坏览},考慮一下規(guī)格化浮點(diǎn)數(shù)。例題源自我的匯編語(yǔ)言筆記。
題目
給定一個(gè)浮點(diǎn)格式(IEEE 754),有k位指數(shù)和n位小數(shù),對(duì)于下列數(shù),寫(xiě)出階碼E、尾數(shù)M、小數(shù)f和值V的公式。另外,請(qǐng)描述其位表示。
數(shù)5.0; 能夠被準(zhǔn)確描述的最大奇數(shù); 最小的正規(guī)格化數(shù)。
解決
前置知識(shí)一:IEEE 754
IEEE 754約定,計(jì)算機(jī)中浮點(diǎn)數(shù)二進(jìn)制表示為:
數(shù)字形式:
符號(hào):s 尾數(shù):M,是一個(gè)位于區(qū)間[1.0, 2.0)內(nèi)的小數(shù) 階碼:E
編碼形式:
s | exp | frac |
---|
exp域:E(注意,E要進(jìn)行變換,再存儲(chǔ)在exp中); frac域:M。
前置知識(shí)二:規(guī)格化浮點(diǎn)數(shù)(Normalized)
這里討論到規(guī)格化浮點(diǎn)數(shù)(Normalized):
滿足條件:exp不全為0且不全為1。 真實(shí)的階碼值需要減去一個(gè)偏置(biased)量: 單精度數(shù):127(Exp:1...254,E:-126...127) 雙精度數(shù):1023(Exp:1...2046,E:-1022...1023) ,e = exp的域的位數(shù) E = Exp - Bias Exp:exp域所表示的無(wú)符號(hào)數(shù)值 Bias的取值: frac的第一位隱含1:M = 1.xxx...x_2 因此第一位的“1”可以省去,xxx...x:bits of frac Minimum when 000...0 ( ) Maximum when 111...1 ( )
前置工作一:整理變量關(guān)系
則E為
E最大值為 。(為什么不是 呢?因?yàn)橛幸?guī)定:exp全部取1為“非規(guī)格化浮點(diǎn)數(shù)”,因此規(guī)格化浮點(diǎn)數(shù)中exp不能全部取1,頂多為(1)*(0)
)
E的最小值為 。(為什么不是 呢?因?yàn)橛幸?guī)定:exp全部取0為“非規(guī)格化浮點(diǎn)數(shù)”,因此規(guī)格化浮點(diǎn)數(shù)中exp不能全部取0,頂多為(0)*(1)
)
前置工作二:總結(jié)特性
拋開(kāi)例題,來(lái)看一個(gè)例子:
8位浮點(diǎn)數(shù)表示:exp域?qū)挾葹? bits,frac域?qū)挾葹? bits。則,其偏置量的值為2^(4-1) - 1 = 7. 其他規(guī)則符合IEEE 754規(guī)范。
取值范圍如下表。
s | exp | frac | E | value |
---|---|---|---|---|
0 | 0000 | 000 | -6 | 0 |
0 | 0000 | 001 | -6 | 1/8 * 1/64 = 1/512 |
0 | 0000 | 010 | -6 | 2/8 * 1/64 = 2/512 |
... | ||||
0 | 0000 | 110 | -6 | 6/8 * 1/64 = 6/512 |
0 | 0000 | 111 | -6 | 7/8 * 1/64 = 7/512 |
0 | 0001 | 000 | -6 | 8/8 * 1/64 = 8/512 |
0 | 0001 | 001 | -6 | 9/8 * 1/64 = 9/512 |
... | ||||
0 | 0110 | 110 | -1 | 14/8 * 1/2 = 14/16 |
0 | 0110 | 111 | -1 | 15/8 * 1/2 = 15/16 |
0 | 0111 | 000 | 0 | 8/8 * 1 = 1 |
0 | 0111 | 001 | 0 | 9/8 * 1 = 9/8 |
0 | 0111 | 010 | 0 | 10/8 * 1 = 10/8 |
... | ||||
0 | 1110 | 110 | 7 | 14/8 * 128 = 224 |
0 | 1110 | 111 | 7 | 15/8 * 128 = 240 |
0 | 1111 | 000 | n/a | inf |
可以看出,假設(shè)frac有f位,則M可視為:
其中,C是整數(shù),由frac決定,即 ;
并且C滿足 。
則浮點(diǎn)數(shù)V的十進(jìn)制即為:
也可寫(xiě)作 :
其中, 、 分別為exp、frac位數(shù),為常數(shù)。
解決問(wèn)題一:數(shù)0.5
較為簡(jiǎn)單,直接解決如下。
0.5???//?轉(zhuǎn)換為二進(jìn)制?==>
0.1???//?移動(dòng)小數(shù)點(diǎn),使其在最左邊的1之后
M??=?1.0?//?小數(shù)點(diǎn)后的數(shù)字存儲(chǔ)在frac中
E?=?-1?//?因?yàn)槭亲笠?br>frac=?0*?//?共n位
exp?=?E?+?Bias
?=?-1?+?(2^(e-1)?-?1)
則,位的描述為:
s | exp | frac |
---|---|---|
0 | bin(-1 + (2^(e-1) - 1)) | 00....(共n位) |
解決問(wèn)題二:能夠被準(zhǔn)確描述的最大奇數(shù)
根據(jù)前置工作二,可以看出,對(duì)于規(guī)格化浮點(diǎn)數(shù)可化簡(jiǎn)為:
現(xiàn)在的任務(wù)有兩個(gè):
是整數(shù),不能有小數(shù)(則 應(yīng)大于等于 ); 是奇數(shù)( 不是奇數(shù),因此使 為奇數(shù),則 取1,則取 )。
下面分類討論:
情況一:E可以取到f時(shí),
即 時(shí),
取 , 取其能取的最大奇數(shù),對(duì)應(yīng)的二進(jìn)制為: exp:dec2bin( ),frac:1*
(frac全為1)
情況二:E取不到f時(shí),
這種情況不可能,因?yàn)镋取不到f,則很多整數(shù)都不能表示。
解決問(wèn)題三:最小的正規(guī)格化數(shù)
觀察:
則 取 , 、 分別取最小。
由前置工作一, 取 , 取 ,對(duì)應(yīng)的二進(jìn)制為: exp:0*1
,frac:0*
后記:我第一學(xué)習(xí)浮點(diǎn)數(shù)是在2019年年末,當(dāng)時(shí)對(duì)于浮點(diǎn)數(shù)的筆記和理解是有問(wèn)題的。在此感謝一位湖南大學(xué)的朋友(公眾號(hào) / CSDN:梓酥),給我發(fā)郵件,指出我的問(wèn)題~
往期推薦
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!