c語言中float、double、long double在內存中存儲方式

存儲格式中的二機制轉爲浮點數:

    浮點型變量在計算機內存中佔用4個字節(4 Byte),即32-bit,一個浮點數由2部分組成:底數m  和 指數e;ios

  底數部分:使用2進制數來表示此浮點數的實際值;spa

  指數部分:佔用8=bit空間來表示,表示數值範圍:0-255;後面介紹 用於存儲科學計數法中的指數部分,而且採用移位存儲方式;code

具體分析:blog

  浮點數據就是按下表的格式存儲在4個字節中:內存

  Address+0 Address+1 Address+2 Address+3 Contentsinput

  SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
      S部分: 表示浮點數正負,1爲負數,0爲正數。一位便可編譯器

  E部分:指數加上127後的值的二進制數(why是加上了127以後的值? 因爲指數應可正可負,因此IEEE規定,此處算出的次方須減去127纔是真正的指數。因此float的指數可從 -126到128.)it

  M部分:24-bit的底數(底數部分實際是佔用24-bit的一個值,因爲其最高位始終爲 1 ,因此最高位省去不存儲,在存儲中只有23-bit。)io

  特例:浮點數 爲0時,指數和底數都爲0,但此前的公式不成立。由於2的0次方爲1,因此,0是個特例。這個特例也不用認爲去幹擾,編譯器會自動去識別。編譯

 舉例:看下-12.5在計算機中存儲的具體數據:0xC1 0x48 0x00 0x00

  二進制:11000001 01001000 00000000 00000000

   格式:SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM

  可見:

    S: 爲1,是個負數。

    E:(8-bit)爲 10000010 轉爲10進製爲130,130-127=3,即實際指數部分爲3.

    M:(23-bit)爲 10010000000000000000000。底數其實是:1.10010000000000000000000

  如今,咱們經過指數部分E的值來調整底數部分M的值。

    調整方法爲:若是指數E爲負數,底數的小數點向左移,若是指數E爲正數,底數的小數點向右移。小數點移動的位數由指數E的絕對值決定。

    這裏,E爲正3,使用向右移3爲即得: 1100.10000000000000000000

  轉換過程:小數點左邊的1100 表示爲 (1 × 2^3) + (1 × 2^2) + (0 × 2^1) + (0 × 2^0), 其結果爲 12 。

        小數點右邊的 .100… 表示爲 (1 × 2^-1) + (0 × 2^-2) + (0 × 2^-3) + ... ,其結果爲.5 。

   以上二值的和爲12.5, 因爲S 爲1,使用爲負數,即-12.5 。因此,16進制 0XC1480000 是浮點數 -12.5 。

浮點數轉存儲格式的二進制數:

  下面看下如何將一浮點數裝換成計算機存儲格式中的二進制數。 舉例將17.625換算成 float型。

  一、轉爲二進制:10001.101

  二、小數點,左移4位,變成1.0001101

  三、這樣底數爲:1.0001101, 指數爲:4+127=131,二進制位:1000011

  四、符號位爲0,由於是正數;

  五、合併:0 1000011  0001101後面補0,補成32-bit;

  六、轉成16進制:轉換成16進制:0x41 8D 00 00 

浮點數轉成二進制代碼形式代碼:

 1 #include<iostream>
 2 using namespace std;
 3 
 4 #define uchar unsigned char
 5 
 6 void binary_print(uchar c)
 7 {
 8         for(int i = 0; i < 8; ++i)
 9         {
10                 if((c << i) & 0x80)
11                         cout << '1';
12                 else cout << '0';
13         }
14         cout << ' ';
15 }
16 
17 int main()
18 {
19         float a;
20         uchar c_save[4];
21         uchar i;
22         void *f;
23         f = &a;
24 
25         cout<<"pls input a float num:";
26         for(i=4;i!=0;i--)
27                 binary_print(c_save[i-1]);
28         cout<<endl;
29 
30         return 0;
31 }

  C標準規定,float類型必須至少能表示6位有效數字,就像33.333 333這樣的數字的小數點後的前6位;那麼whyfloat能表示6位有效數字呢?

   解釋以下:十進制中的9,在二進制中的表示形式是1001,這也就是說: 表示十進制中的一位數在二進制中須要4bit,因此咱們如今float中具備24bit的精度,因此float在十進制中具備24/4=6,因此在十進制裏,float可以精確到小數點後6位;

  double呢?其實和float原理是同樣的,只是double的位數更長一些而已;

        

   注意點,double類型數據操做比float型運算要慢不少;

浮點值的上溢和下溢

  假設系統中最大的float值爲34E38,並進行以下操做:

    float toobig = 3.4E38 * 100.0f ;

           printf("%e\n", toobig);

  會發生什麼呢?這是一個上溢(overflow)的例子。當計算結果是一個大得不能表達的數時,會發生上溢。

   相對應的,當表示一個float能表示的最小數時,對這個數進行除2操做,將會發生下溢。

相關文章
相關標籤/搜索