1. 程式人生 > >C語言學習總結:浮點型在記憶體中的儲存

C語言學習總結:浮點型在記憶體中的儲存

我們都知道,對於整形來說,資料存放記憶體中存放的是補碼。但是對於浮點型來說,在記憶體中存放的是否也是補碼呢?

舉個例子:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int n = 9;
	float *pFloat = (float *)&n;//強制轉換型別
	printf("n的值為:%d\n",n);
	printf("*pFloat的值為:%f\n",*pFloat);

	*pFloat = 9.0;
	printf("num的值為:%d\n",n);
	printf("*pFloat的值為:%f\n",*pFloat);
	return 0;
}

num和*pFloat中存放的是同一個數,但是結果卻不一樣。所以,浮點型的儲存方式一定和整形是不一樣的。

那麼,浮點型資料是怎麼儲存的呢?

1.根據國際標準IEEE(電氣和電子工程協會)754,任意一個二進位制浮點數可以表示為下面的形式:

(-1)^S*M*2^E

a.(-1)^S表示符號位,當S=0時,表示正數,當S=1時,表示負數。

b.M表示有效數字,大於等於1,小於2。

c.2^E表示指數位。

例如:5.5寫成二進位制為101.1,相當於1.011*2^2,那麼,S=0,M=1.011,E=2。

2.IEEE 745規定:對於32位的浮點數,最高的1位是符號位S,接著的8位是指數E,剩下的23位為有效數字M。

                                                                   單精度浮點數儲存模型

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

                                                                       雙精度浮點數儲存模型

3.IEEE 754對有效數字M和指數E,還有一些特別規定。

有效數字M:1<M<2,也就是說,M寫成1.xxxxxxx的形式,其中xxxxxxx表示小數部分。

IEEE 754規定,在計算機內部儲存M時,預設這個數的第一位總是1,因此可以被捨去,只儲存小數部分。比如儲存1.011時,只儲存011,後面的位數補0就可以了,等到讀取的時候,再把第一位的1補上去。

指數E:

首先,E為一個無符號整數(unsigned int)

如果E為8位,它的取值範圍為0~255;如果E為11位,它的取值範圍為0~2047。但是,我們知道,科學計數法是可以出現負數的,所以IEEE 754規定,存入記憶體的E是真實值加上一個中間數,對於8位的E,中間數是127,對於11位的E,中間數是1023。比如,2^2的E是2,所以儲存為32位浮點數時,必須儲存為2+127=129,即10000001。

然後,指數E還可以被分為三種情況:

E不全為0或不全為1

這個就是正常情況,取出記憶體中的數時,指數E的計算值減去127(或1023),得到真實值,再將有效數字M前加上第一位的1。

E全為0

這時,浮點數的指數E等於1-127(或1-1023)即為真實值,有效數字M不再加上第一位的1,而是還原為0.xxxxxxx的小數。這樣做是為了表示正負零,以及接近於0的很小的數字。

E全為1

這時,有效數字M全為0,表示正負無窮大。

好了,現在我們回到剛開始的例題,在第一部分中,整形數字9若還原成浮點數就變成了0,這是為什麼呢?

首先,將00000000000000000000000000001001拆分,第一位符號位S=0,後面8位的指數E=00000000,最後23位有效數字M=00000000000000000001001。由於指數E全為0,符合上述第二種情況,因此,浮點數是一個很小的接近於0的正數,所以用十進位制小數表示為0.000000。

在第二部分中,浮點數9.0用十進位制表示是一個很大的數。這又是為什麼呢?

首先,浮點數9.0等於二進位制的1001.0,即1.001*2^3。那麼,S=0,M=1.001,E=3+127=130。

就是這樣:0 10000010 00100000000000000000000

這個32位的二進位制數,還原成十進位制數,正是1091567616。