C 浮點數在記憶體中的儲存詳解

2022-09-20 09:06:08 字數 2570 閱讀 7801

目錄

程式設計客棧我們在碼**的時候,經常遇到過以整數形式存入,浮點數形式輸出;或者浮點數形式存入整數形式輸出。輸出的結果往往讓人意想不到,那麼,為什麼會發生這樣的變化,又是什麼導致發生變化,接下來,就讓我們從儲存內部結構出發,帶你深度解刨!

我們以乙個例子來說明一切

#include

int main()

這個例子我們將n以整數形式輸入,再定義乙個指標變數來存n的位址,,分別將n以整數、浮點數形式輸出。

輸出結果如下

n和*pfloat在記憶體中明明是同乙個數,為什麼浮點數和整數的解讀結果會差別那麼大?

要理解這個結果,一定要搞懂程式設計客棧浮點數在計算機內部的表示方法。

根據國際標準ieee(電氣和電子工程協會)754,任意乙個二進位制浮點數v可以表示成下面的形式

(-1)^s*m*2^e(-1)^s表示符號位,當s=0,v為正數;當s=1,v為負數。m表示有效數字,大於等於1,小於2.2^e表示指數字。舉例來說:

十進位制的5.0,寫成二進位制是101.0,用科學計數法就是:1.01*2^2(模擬於十進位制的科學計數法:20000=2*10^4);

由於5.0是正數,所以s=0,根據上面,m=1.01,e=2。

所以,寫成浮點數就是:(-1)^0*1.01*2^2。

ieee754規定:

對於32位的浮點數,最高的1位是符號位s,接著的8位是指數e,剩下的23位為有效數字m。

對於64位的浮點數,最高的1位是符號位s,接著的11位是指數e,剩下的52位為有效數字m。

前面我們給了m的範圍是1≤m<2,那麼為什麼範圍是這麼多?我們知道,二進位制最高位為1,用科學計數法表示以後,m的形式為1.***xx的形式,其中***xx表示小數部分。

ieee754規定,在計算機內部儲存m是,預設這個數的第一位總是1,因此可以被捨去,只儲存後面的***xx部分。比如儲存1.01的時候,只儲存01,等到讀取的時候,再把第一位的1加上去。這樣做的目的是節省1位有效數字。以32位浮點數為例,留給m只有23位,將第一位的1捨去以後,等於可以儲存24位有效數字。

至於指數e,情況就比較複雜。

首先,e為乙個無符號整型(unsingde int)

這意味著,如果e為8位,它的取值範圍為0~255;如果e是11位,它的取值範圍為0~204。但是我們知道,科學計數法中的e是可以出現負數的,所以ieee754規定,存入記憶體時e的真實值必須再加上乙個中間數,對於8位的e,這個中間數是127;對於1位的e,這個中間數是1023。

比如:2^10的e是10,所以儲存成32位浮點數時,必須儲存成10+127=137,即化為二進位制為10001001。

對於指數e從記憶體中取出還可以再分成三種情況:

(1) e不全為0或不全為1

這時,浮點數就採用下面的規則表示,即指數e的計算值減去127(或1023),得到真實值,再將有效數字m前加上第一位的1。

比如:0.5(1/2)的二進位制形式為0.1,由於規定正數部分必須為1,即小數點右移1位,則為1.0*2^www.cppcns.com(-1),其階碼為-1+127=126,表示為01111110而尾數1.0去掉整數部分為0,補齊0到23位00000000000000000000000,則其二進位制表示形式為:

0  01111110  00000000000000000000000

(2)e全為0

這時,浮點數的指數e等於1-127(或者1023)即為真實值,有效數字m不再加上第一位的1,而是還原為0.***xx的小數。這樣做是為了表示±0,以及接近程式設計客棧於0的很小的數字。

(3)e全為1

這時,如果有效數字m全為0,表示±無窮大(正負取決於符號位s);

(1)printf("n的值為:%d\n",n);

n是以整數存入的,在記憶體中的儲存為:

輸出是整數,所以 輸出的還是9。

(2)printf("*pfloat的值為:%f\n",*pfloat);

*pfloat相當於n的值,但輸出卻是以浮點數的形式輸出,但存入還是以整數形式存入,這是,記憶體就會把存入的0 00000000 00000000000000000001001以浮點數形式處理,這裡相當於,第一位就是s,即s=0,e全為0,剩下的為m,即m=00000000000000000001001。

(3)printf("n的值為:%d\n",n);

此時,*pfloat=9.0,也就是將9.0以浮點數形式存入,以整數形式取出。

根據前面,我們寫出9.0的儲存:

由於是正數,所以s=0;

9轉換為二進位制為1001,科學計數法:1.001*2^3;

∴e=3(屬於第一種,既不是全0,也不是全1),存入時要加上127,則e的真實值為:e=3+127=130,化為二進位制1000 0010

m後面補0補全23位,即:001  0000 0000 0000 0000

所以浮點數在記憶體中的儲存為:

最後輸出以整數形式輸出,即把0 100000010 00100000000000000000000視為要輸出的數的補碼,但輸出的是原碼,因為最高位為0,所以這個數是正數,原反補相同,則輸出這個數,化為十進位制就是:

(4)printf("*pfloat的值為:%f\n",*pfloat);

以浮點數形式存入,以浮點數形式輸出,最後輸出還是9.000000,保留6位小數。

詳解浮點數在記憶體中的儲存

浮點數的家族包含 float,double,long double型別。先寫乙個演示 include intmain 那結果到底對不對呢?可以看出結果和我們預想的完全不一樣,同時夜說明了乙個問題 浮點數和整數在記憶體中的儲存方式是不一樣的。根據國際標準ieee754規定,任意乙個二進位制浮點數v可以...

浮點數在記憶體中的儲存

浮點數在記憶體中的儲存方式與整型數字是不同的,對浮點數的儲存實際上是對ieee754中規定的s m e的儲存。浮點數 float double long double 根據國際標準ieee754,任意乙個二進位制浮點數可以被表示成下面的形式 ieee754規定 對於32位的浮點數,最高的1個位元位為...

浮點數在記憶體中的儲存

浮點數在記憶體中的儲存 常見浮點數型別 float,double,long double.那麼浮點數在記憶體中又是如何儲存的呢,它會和整數一樣嗎?那它的小數點又是如何儲存的呢 int main 執行結果為 n和 pfloat在記憶體中明明是同一位置同一數字,為什麼浮點數和整數的讀取結果會不一樣.說明...