天天看點

c語言中float、double、long double在記憶體中存儲方式float:浮點數轉存儲格式的二進制數:十進制的小數到二進制的轉換二進制到十進制的轉換float、double、long double精度及數值範圍了解

float:

浮點型變量在計算機記憶體中占用4個位元組(4 Byte),即32-bit,一個浮點數由2部分組成:底數m 和 指數e;

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

指數部分:占用8bit即1byte空間來表示,表示數值範圍:0-255;後面介紹 用于存儲科學計數法中的指數部分,并且采用移位存儲方式;

浮點資料就是按下表的格式存儲在4個位元組中:

  SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM

  • S部分: 表示浮點數正負,1為負數,0為正數。一位即可
  • E部分:指數加上127後的值的二進制數(why是加上了127之後的值? 由于指數應可正可負,是以IEEE規定,此處算出的次方須減去127才是真正的指數。是以float的指數可從 -126到128.)
  • M部分:24-bit的底數(底數部分實際是占用24-bit的一個值,由于其最高位始終為 1 ,是以最高位省去不存儲,在存儲中隻有23-bit。)
  • 特例:浮點數 為0時,指數和底數都為0,但此前的公式不成立。因為2的0次方為1,是以,0是個特例。這個特例也不用認為去幹擾,編譯器會自動去識别。

舉例:看下float f = 97.0f;在計算機中存儲的具體資料:0xc2 0xc2 0x00 0x00

二進制:1 10000101 1000010 00000000 00000000

S: 為1,是個負數。

E:(8-bit)為 10000101 轉為10進制為133,133-127=6,即實際指數部分為6.

M:(23-bit)為 10000100000000000000000。底數實際上是:1.10000100000000000000000

現在,我們通過指數部分E的值來調整底數部分M的值。

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

    這裡,E為正6,使用向右移6為即得: 1100001.00000000000000000

轉換過程:小數點左邊的1000010表示為 (1 * 2^6)+(1 * 2 ^ 5)+(1 * 2^0) =97 , 其結果為 97 。

       小數點右邊的 .0000000000000000 表示為0 ,其結果為.0 。

以上二值的和為97.0, 由于S 為1,使用為負數,即-97.0 。是以,16進制 0xc2c20000 是浮點數 97.0f 。

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

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

  1、轉為二進制:10001.101

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

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

  4、符号位為0,因為是正數;

  5、合并:0 1000011 0001101後面補0,補成32-bit;

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

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

#include<iostream>
using namespace std;
#define uchar unsigned char

void binary_print(uchar c)
{
        for(int i = 0; i < 8; ++i)
        {
                if((c << i) & 0x80)
                        cout << '1';
                else cout << '0';
        }
        cout << ' ';
}

int main()
{
        float a;
        uchar c_save[4];
        uchar i;
        void *f;
        f = &a;

        cout<<"pls input a float num:";
        cin >> f;
        for(i=4;i!=0;i--)
                binary_print(c_save[i-1]);
        cout<<endl;

        return 0;
}
           

十進制的小數到二進制的轉換

十進制的小數轉換為二進制,主要是小數部分乘以2,取整數部分依次從左往右放在小數點後,直至小數點後為0

eg:十進制的0.125,要轉換為二進制的小數

0.125 * 2 = 0.25    取0
0.25 * 2 = 0.5      取0
0.5 *2 = 1			取1
即:二進制為0.001
           

二進制到十進制的轉換

二進制的小數轉換為十進制主要是乘以2的負次方,從小數點後開始,依次乘以2的負一次方,2的負二次方,2的負三次方等

二進制數0.001轉換為十進制
第一位為0,則0*1/2,即0乘以2負 一次方
第二位為0,則0*1/4,即0乘以2的負二次方
第三位為1,則1*1/8,即1乘以2的負三次方
各個位上乘完之後,相加,0*1/2+0*1/4+1*1/8得十進制的0.125
           

float、double、long double精度及數值範圍了解

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

解釋如下:十進制中的9,在二進制中的表示形式是1001,這也就是說: 表示十進制中的一位數在二進制中需要4bit,是以我們現在float中具有24bit的精度,是以float在十進制中具有24/4=6,是以在十進制裡,float能夠精确到小數點後6位;

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

  

c語言中float、double、long double在記憶體中存儲方式float:浮點數轉存儲格式的二進制數:十進制的小數到二進制的轉換二進制到十進制的轉換float、double、long double精度及數值範圍了解

IEEE754浮點數的表示方法。C語言裡對float類型資料的表示範圍為-3.410^ 38~+3.410^ 38。double為-1.710^ -308~ 1.710^ 308,long double為-1.210^ -4932~1.210^4932.

c語言中float、double、long double在記憶體中存儲方式float:浮點數轉存儲格式的二進制數:十進制的小數到二進制的轉換二進制到十進制的轉換float、double、long double精度及數值範圍了解

究竟如何計算該範圍,分析如下:

對于單精度浮點數(float)來說,符号位一位,指數位8位,尾數23位。指數能夠表示的指數範圍為-128~127。尾數為23位。

float和double的精度是由尾數的位數來決定的。浮點數在記憶體中是按科學計數法來存儲的,其整數部分始終是一個隐含着的“1”,由于它是不變的,故不能對精度造成影響。float:2 ^ 23 = 8388608,所得十進制共七位,這意味着最多能有7位有效數字,但絕對能保證的為6位,也即float的精度為6~7位有效數字;double:2^52 = 4503599627370496,所得十進制共16位,同理,double的精度為15 ~ 16位。

其中負指數決定了浮點數所能表達的絕對值最小的非零數;而正指數決定了浮點數所能表達的絕對值最大的數,也即決定了浮點數的取值範圍。float的範圍為-2^ 128 ~ +2^ 128,也即-3.40E+38 ~ +3.40E+38;double的範圍為-2^ 1024 ~ +2^1024,也即-1.79E+308 ~+1.79E+308。

以float為例,如下表

c語言中float、double、long double在記憶體中存儲方式float:浮點數轉存儲格式的二進制數:十進制的小數到二進制的轉換二進制到十進制的轉換float、double、long double精度及數值範圍了解

例如:

+1.111111111111111111111 12^ 127(小數點後面23個1,由于尾數的範圍1~2,其最高位總為1,故隻需存取小數部分,是以小數為是23位1),約等于12^ 127=3.410^ 38。為3.410^38負數亦然。

Double的計算與此類似,double的符号位為63位,指數為62~52位,共11位。表示的範圍為-1024~1023。尾數為51~0。表示的範圍為+1.1111111111111111…1111 1 * 2^ 1023(小數點後面52個1)為1.7*10^308。負數亦然。

繼續閱讀