該文主要介紹一個浮點數在計算機中的表示咆瘟,屬于很底層的知識點
介紹計算機如何表示浮點數之前村砂,先了解一下日常生活中肥哎,我們人類如何使用十進制表示一個很大的數(假設這個要表示的數是二百萬欧宜,200 0000)坐榆。假如是一個更大的數,表示起來將更加不方便冗茸,因此席镀,我們可以使用科學計數法表示為2*10^6 ;0.000002則常常表示為2*10^-6夏漱。
計算機表示二進制浮點數采用了類似的表示方法豪诲。假入有一個數,1101 0000挂绰。先不管這個數對應的十進制值是多少屎篱,考慮一下如何在計算機中存儲。像unsigned int 那樣直接將對應的位存儲在相應的空間完全沒有問題扮授,但是如果這個數后面還有很多個0呢芳室,因此,我們這里將這個數看作1.101*2^7(本文不對該表示法原理多做介紹)刹勃,然后將1.101和7分別存儲在相應空間的兩個部分,就像我們把東西分門別類放在收納袋里一樣嚎尤。
以上只是一個粗淺的策略荔仁,僅限于我和看了我這個策略的人能夠共同遵守,我們這樣把一個數放在收納袋中拿給別人,別人并不能立即把收納袋中的數復原乏梁。因此IEEE設計了一個更加巧妙并有前瞻性的收納袋次洼,想要存儲數的人把數的各部分按照規(guī)則放好,想要讀取這個數的人按照規(guī)則將各部分取出拼湊即可獲得該數遇骑。(這讓我感到溝通即妥協)
1. IEEE浮點標準
V=(-1)^s * M * 2^E
- 符號(sign):s決定該數的正負
- 尾數(significand):M是一個二進制小數
- 階碼(exponent):E對浮點數加權(也許有人對這個理解的不夠卖毁,我這里暫時無法對此詳細解釋)
有些概念不好理解,或者表示不清晰落萎。我們用一個數來協助理解——1101 0000 0000 0000 0000亥啦。該數用浮點標準表示為(-1)^0 * 1.101 * 2^15,在這個例子中练链,s=-1翔脱,M=1.101,E=15所以我們最終存儲的就是這三個參數媒鼓。
浮點數表示有兩種届吁,float和double,區(qū)別在于M和E的取值范圍绿鸣。
根據E的取值疚沐,被編碼的值分成三種情況。E是浮點數的權值潮模,通俗說就是后面究竟有多少個值濒旦。怎么理解權值這個概念呢?我們都是1.101再登,但是我后面有15個0尔邓,你后面只有1個0,那我權重15就可以秒殺你的權重1锉矢,這就是權的絕對力量梯嗽。我們不一樣!
當E上每一位都為0的時候沽损,為非規(guī)格化的值灯节;當E上每一位都為1的時候,為特殊值绵估;剩余的情況即為規(guī)格化的值炎疆。
1.1 規(guī)格化的值
1.1.1 exp字段
考慮科學計數法表示整數的時候,E取值為正數或0国裳;表示小數的時候形入,E取值為負數,因此E應為一個有符號整數缝左。這里沒有采取再設置一個E的符號位的方式亿遂,而是采用偏置形式來表示有符號整數浓若。
簡單說來就是設定一個數,我們稱之Bias蛇数。若E的原始值大于Bias(在Bias的右邊)挪钓,則階碼的值為正數;若E的原始值小于Bias(在Bias的左邊)耳舅,則階碼的值為負數碌上。很明顯這里將exp字段設計的更加復雜也是為了妥協,至于為什么這里采用偏執(zhí)而不是設置符號位的方式浦徊,我不清楚馏予。
E=e-Bias
e是無符號數
Bias=2^(k-1)-1
以exp字段為1001 0011為例,Bias為0111 1111=127
E=1001 0011 - 0111 1111=0001 0011=19
1.1.2 frac字段
frac字段為小數字段辑畦,鑒于一個二進制小數可以化為1.x*2^E的形式吗蚌,可以將1.x中的1省略不表示,反正每一個數最終都包含1纯出,這就叫做共識蚯妇。因為省略了1暂筝,因此在最終計算結果的時候需要加1,尾數定義為M=1+f焕襟,f的二進制表示為0.fn-1 ... f1 f0
1.2 非規(guī)格化的值
非規(guī)格化的值exp字段全為0,階碼值E=1-Bias鸵赖,尾數M=f务漩。
非規(guī)格化數兩個用途:
- 表示數值0
- 表示非常接近于0.0的數
在規(guī)格化值的規(guī)則設定中,我們默認M是一個范圍為(1<=M<2)的數它褪,這就導致我們可以表示0.00...01這個很接近0的小數饵骨,卻沒法用浮點數表示0∶4颍考慮到這點居触,我們規(guī)定當exp字段全為0的時候,階碼值E=1-Bias(127)老赤,而根據公式M*2^E可以看出轮洋,無論M在表示范圍內取何值,都避免不了結果趨近于0.0的命運抬旺,此即權值對數的影響弊予。相對于人而言,無論我們掌握了多少的技能嚷狞,不會思考都將限制我們的人生块促,這就是為什么我現在的人生如此悲慘的根由吧荣堰。
回到主線床未,按照規(guī)格化的方式(M=1+f)竭翠,雖然我們也最終可以無限接近于0.0,但是總有個1在那里薇搁,因此我們設定了非規(guī)格化的規(guī)則斋扰,M=f。這樣一來啃洋,我們最終將的到0(M=0)传货。
需要注意的是,根據s字段的值宏娄,我們將會有+0.0(s=1)和-0.0(s=0)问裕。這兩個值在某些方面被認為是不同的,至少在存儲中不同孵坚。
1.3 特殊值
exp字段全為1粮宛。
我們還是先分析權,E將會是一個很大的值卖宠,導致權很大巍杈,可以用來表示無窮。
若frac字段全為0扛伍,得到的值表示無窮筷畦,當s=0為+無窮,s=1表示-無窮刺洒。
若frac字段不全為0鳖宾,結果值被稱為NaN鼎文,即不是一個值(Not a Number)纸泡,可以用來表示某些運算導致出現非實數的結果女揭,例如對-1求平方根,或計算正無窮-正無窮磷仰。
2. 示例
假設一個基于IEEE浮點格式的5位浮點表示灶平,1個符號位、2個階碼位(k=2)和2個小數位(n=2)罐监,列舉這個5位浮點表示的全部非負取值范圍弓柱。
位 | e | E | $2^E$ | f | M | $2^E*M$ | V | 十進制 |
---|---|---|---|---|---|---|---|---|
0 00 00 | 0 | -1 | $1\over2$ | $0\over4$ | $0\over4$ | $1\over2$ * $0\over4$ | $0\over8$ | +0.0 |
0 00 01 | 0 | -1 | $\frac{1}{2}$ | $1\over4$ | $1\over4$ | $1\over2$ * $1\over4$ | $1\over8$ | 0.125 |
0 00 10 | 0 | -1 | $1\over2$ | $2\over4$ | $2\over4$ | $1\over2$ * $2\over4$ | $2\over8$ | 0.25 |
0 00 11 | 0 | -1 | $1\over2$ | $3\over4$ | $3\over4$ | $1\over2$ * $3\over4$ | $3\over8$ | 0.375 |
0 01 00 | 1 | 0 | 1 | $0\over4$ | $4\over4$ | 1* $4\over4$ | $4\over4$ | 1 |
0 01 01 | 1 | 0 | 1 | $1\over4$ | $5\over4$ | 1* $5\over4$ | $5\over4$ | 1.25 |
0 01 10 | 1 | 0 | 1 | $2\over4$ | $6\over4$ | 1* $6\over4$ | $6\over4$ | 1.75 |
0 01 11 | 1 | 0 | 1 | $3\over4$ | $7\over4$ | 1* $7\over4$ | $7\over4$ | 1.75 |
0 10 00 | 2 | 1 | 2 | $0\over4$ | $4\over4$ | 2* $4\over4$ | $8\over4$ | 2 |
0 10 01 | 2 | 1 | 2 | $1\over4$ | $5\over4$ | 2* $5\over4$ | $10\over4$ | 2.5 |
0 10 10 | 2 | 1 | 2 | $2\over4$ | $6\over4$ | 2* $6\over4$ | $12\over4$ | 3 |
0 10 11 | 2 | 1 | 2 | $3\over4$ | $7\over4$ | 2* $7\over4$ | $14\over4$ | 3.5 |
0 11 00 | 3 | 2 | 4 | $0\over4$ | $4\over4$ | 4* $4\over4$ | $16\over4$ | 4 |
0 11 01 | 3 | 2 | 4 | $1\over4$ | $5\over4$ | 4* $5\over4$ | $20\over4$ | 5 |
0 11 10 | 3 | 2 | 4 | $2\over4$ | $6\over4$ | 4* $6\over4$ | $24\over4$ | 6 |
0 11 11 | 3 | 2 | 4 | $3\over4$ | $7\over4$ | 4* $7\over4$ | $28\over4$ | 7 |