天天看點

浮點數的二進制表示學習筆記

基礎知識:

十進制轉十六進制;

十六進制轉二進制;

IEEE制定的浮點數表示規則;

了解:

目前C/C++編譯器标準都遵照IEEE制定的浮點數表示法來進行float,double運算。這種結構是一種科學計數法,用符号、指數和尾數來表示,底數定為2——即把一個浮點數表示為尾數乘以2的指數次方再添上符号。下面是具體的規格:

             符号位     階碼      尾數     長度

float           1          8        23      32

double          1         11        52      64

以下通過幾個例子講解浮點數如何轉換為二進制數

例一:

已知:double類型38414.4。

求:其對應的二進制表示。

分析:double類型共計64位,折合8位元組。由最高到最低位分别是第63、62、61、……、0位:

    最高位63位是符号位,1表示該數為負,0表示該數為正;

    62-52位,一共11位是指數位;

    51-0位,一共52位是尾數位。

     步驟:按照IEEE浮點數表示法,下面先把38414.4轉換為十六進制數。

     把整數部和小數部分開處理:整數部直接化十六進制:960E。小數的處理:

0.4=0.5*0+0.25*1+0.125*1+0.0625*0+……

     實際上這永遠算不完!這就是著名的浮點數精度問題。是以直到加上前面的整數部分算夠53位就行了。隐藏位技術:最高位的1不寫入記憶體(最終保留下來的還是52位)。

    如果你夠耐心,手工算到53位那麼因該是:38414.4(10)=1001011000001110.0110011001100110011001100110011001100(2)

科學記數法為:1.001011000001110 0110011001100110011001100110011001100,右移了15位,是以指數為15。或者可以如下了解:

1.001011000001110 0110011001100110011001100110011001100×2^15

     于是來看階碼,按IEEE标準一共11位,可以表示範圍是-1024 ~ 1023。因為指數可以為負,為了便于計算,規定都先加上1023(2^10-1),在這裡,階碼:15+1023=1038。二進制表示為:100 00001110;

    符号位:因為38414.4為正對應 為0;

    合在一起(注:尾數二進制最高位的1不要):

01000000 11100010 11000001 110 01100  11001100  11001100  11001100  11001100

例二:

已知:整數3490593(16進制表示為0x354321)。

求:其對應的浮點數3490593.0的二進制表示。 

解法如下:

先求出整數3490593的二進制表示:

 H:    3     5    4    3    2     1   (十六進制表示)

 B:   0011  0101 0100 0011 0010  0001 (二進制表示)

        │←─────  21────→│

即: 

               1.1010101000011001000012×221

可見,從左算起第一個1後有21位,我們将這21為作為浮點數的小數表示,單精度浮點數float由符号位1位,指數域位k=8位,小數域位(尾數)n=23位構成,是以對上面得到的21位小數位我們還需要補上2個0,得到浮點數的小數域表示為:

         1 0101 0100 0011 0010 0001 00

float類型的偏置量Bias=2k-1-1=28-1-1=127,但還要補上剛才因為右移作為小數部分的21位,是以偏置量為127+21=148,就是IEEE浮點數表示标準:

                          V = (-1)s×M×2E

                    E = e-Bias

中的e,此前計算Bias=127,剛好驗證了E=148-127=21。

将148轉為二進制表示為10010100,加上符号位0,最後得到二進制浮點數表示1001010010101010000110010000100,其16進制表示為:

 H:     4        A       5          5         0         C         8        4  

 B:  0100   1010   0101    0101   0000   1100  1000   0100

                    |←────      21        ─────→   |

     1|←─8   ─→||←─────       23       ─────→ |

這就是浮點數3490593.0(0x4A550C84)的二進制表示。

例三:

0.5的二進制形式是0.1

它用浮點數的形式寫出來是如下格式

0                01111110                 00000000000000000000000

符号位           階碼                       小數位

正數符号位為0,負數符号位為1

階碼是以2為底的指數

小數位表示小數點後面的數字

下面我們來分析一下0.5是如何寫成0 01111110 00000000000000000000000

首先0.5是正數是以符号位為0

再來看階碼部分,0.5的二進制數是0.1,而0.1是1.0*2^(-1),是以我們總結出來:

要把二進制數變成(1.f)*2^(exponent)的形式,其中exponent是指數

而由于階碼有正負之分是以階碼=127+exponent;

即階碼=127+(-1)=126 即 01111110

餘下的小數位為二進制小數點後面的數字,即00000000000000000000000

由以上分析得0.5的浮點數存儲形式為0 01111110 00000000000000000000000  

注:如果隻有小數部分,那麼需要右移小數點. 比如右移3位才能放到第一個1的後面, 階碼就是127-3=124.

例四   (20.59375)10 =(10100.10011 )2

首先分别将整數和分數部分轉換成二進制數: 

20.59375=10100.10011 

然後移動小數點,使其在第1,2位之間 

10100.10011=1.010010011×2^4   即e=4 

于是得到: 

S=0, E=4+127=131, M=010010011 

最後得到32位浮點數的二進制存儲格式為: 

0100 1001 1010 0100 1100 0000 0000 0000=(41A4C000)16

例五:

-12.5轉為單精度二進制表示

12.5: 

1. 整數部分12,二進制為1100; 小數部分0.5, 二進制是.1,先把他們連起來,從第一個1數起取24位(後面補0): 

1100.10000000000000000000 

這部分是有效數字。(把小數點前後兩部分連起來再取掉頭前的1,就是尾數) 

2. 把小數點移到第一個1的後面,需要左移3位(1.10010000000000000000000*2^3), 加上偏移量127:127+3=130,二進制是10000010,這是階碼。 

3. -12.5是負數,是以符号位是1。把符号位,階碼和尾數連起來。注意,尾數的第一位總是1,是以規定不存這一位的1,隻取後23位: 

1 10000010 10010000000000000000000 

把這32位按8位一節整理一下,得: 

11000001 01001000 00000000 00000000 

就是十六進制的 C1480000. 

例六:

2.025675 

1. 整數部分2,二進制為10; 小數部分0.025675, 二進制是.0000011010010010101001,先把他們連起來,從第一個1數起取24位(後面補0): 

10.0000011010010010101001 

這部分是有效數字。把小數點前後兩部分連起來再取掉頭前的1,就是尾數: 00000011010010010101001 

2. 把小數點移到第一個1的後面,左移了1位, 加上偏移量127:127+1=128,二進制是10000000,這是階碼。 

3. 2.025675是正數,是以符号位是0。把符号位,階碼和尾數連起來: 

0 10000000 00000011010010010101001 

01000000 00000001 10100100 10101001 

就是十六進制的 4001A4A9.  

例七:

(逆向求十進制整數)一個浮點二進制數手工轉換成十進制數的例子: 

假設浮點二進制數是 1011 1101 0100 0000 0000 0000 0000 0000 

按1,8,23位分成三段: 

1 01111010 10000000000000000000000 

最後一段是尾數。前面加上"1.", 就是 1.10000000000000000000000 

下面确定小數點位置。由E = e-Bias,階碼E是01111010,加上00000101才是01111111(127), 

是以他減去127的偏移量得e=-5。(或者化成十進制得122,122-127=-5)。 

是以尾數1.10(後面的0不寫了)是小數點右移5位的結果。要複原它就要左移5位小數點,得0.0000110, 即十進制的0.046875 。

最後是符号:1代表負數,是以最後的結果是 -0.046875 。

注意:其他機器的浮點數表示方法可能與此不同. 不能任意移植。

再看一例(類似例七):

比如:53004d3e

二進制表示為:

01010011000000000100110100111110

按照1個符号    8個指數          23個小數位劃分

0              10100110         00000000100110100111110

正确的結果轉出來應該是551051722752.0

該怎麼算?

好,我們根據IEEE的浮點數表示規則劃分,得到這個浮點數的小數位是:

 00000000100110100111110

那麼它的二進制表示就應該是:

1.000000001001101001111102× 239

這是怎麼來的呢? 别急,聽我慢慢道來。

标準化公式中的M要求在規格化的情況下,取值範圍1<M<(2-ε)

正因為如此,我們才需要對原始的整數二進制表示做偏移,偏移多少呢?偏移2E。

這個“E”怎麼算?上面的239怎麼得來的呢?浮點數表示中的8位指數為就是告訴這個的。我們知道:

E = e-Bias

那麼根據指數位:

101001102=>16610

即e=166,由此算出E=e-Bias=166-127=39,就是說将整數二進制表示轉為标準的浮點數二進制表示的時候需要将小數點左移39位,好,我們現在把它還原得到整數的二進制表示:

1 00000000100110100111110 0000000000000000

1│←───── 23─────→│← 16─→│

23+16=39,後面接着就是小數點了。

拿出電腦,輸入二進制數1000000001001101001111100000000000000000

轉為十進制數,不正是:551051722752麼!

通過這例六例七,介紹了将整數二進制表示轉浮點數二進制表示的逆過程,還是希望大家不但能掌握轉化的方法,更要了解轉化的基本原理

本文轉自    風雨蕭條 部落格,原文連結: http://blog.51cto.com/1095221645/1553524       如需轉載請自行聯系原作者

繼續閱讀