首頁 > 軟體

C語言詳細分析浮點數在記憶體中的儲存

2022-06-23 14:01:34

浮點數的儲存格式

初步瞭解

首先讓我們通過一段程式碼來認識一下浮點型和整型的區別:

int main()
{
	int n = 9;//將整型9儲存到n中
	float* pFloat = (float*)&n;
	printf("n的值為:%dn", n);
	printf("*pFloat的值為:%fn", *pFloat);
	*pFloat = 9.0;//將浮點型9.0儲存到*pFloat中
	printf("num的值為:%dn", n);
	printf("*pFloat的值為:%fn", *pFloat);
	return 0;
}

從程式碼中我們可以看到,n和*pFloat指向的其實是同一塊區域,因為int和float都是4個位元組的資料型別。讓我們來看看最後的輸出結果:

我們可以看到結果還是有些出人意料——

以整形儲存(n = 9),可以用整型正常讀取,但用浮點型讀取就會出現難以預料的情況 ;

同樣的,以浮點型儲存(*pFloat = 9.0),可以用浮點型正常讀取,但是用整型就會出現難以預料的情況。

從這個例子中我們可以知道,浮點型和整型的儲存和讀取方式是完全不同的。

深入探究

從前面的部落格中,我們瞭解到了整型是通過二補數的形式儲存的,那麼浮點型的儲存形式是什麼樣的呢?

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

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

S是符號位(為0時浮點數為正,為1時浮點數為負),M為有效數位(大於1小於2),2^E表示指數位(決定了這個數的大小)。

讓我們來舉例說明:

浮點數8.5f轉換成二進位制為1000.1,S為0,M為1.0001,E為 3

=(-1)^0 * 1.0001 * 2^3

所以我們只要在記憶體中儲存S、M和E三個數位就可以儲存浮點型資料了,實際上也是那麼操作的。

接下來我們用圖來解釋內部的儲存邏輯:

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

我們要知道,E是一個無符號整型數位,這意味著,如果E為8位元,它的取值範圍為0~255;如果E為11位,它的取值範圍為0~2047。

但是,我們知道,科學計數法中的E是可以出現負數的,所以IEEE 754規定,存入記憶體時E的真實值必須再加上一個中間數,對於8位元的E,這個中間數是127;對於11位的E,這個中間數是1023。比如,2^10的E是10,所以儲存成32位元浮點數時,必須儲存成10+127=137,即10001001。

然後,指數E從記憶體中取出還可以再分成三種情況:

E不全為0或不全為1

這時,浮點數就採用下面的規則表示,即指數E的計算值減去127(或1023),得到真實值,再將

有效數位M前加上第一位的1。

以8.5f為例

#include<stdio.h>
// 8.5f
// S為0,M為1.0001,E為 3 + 127
// 0 10000010  00010000000000000000000
// S    E                 M
// 0100 0001 0000 1000 0000 0000 0000 0000
// 轉換為16進位製為41 08 00 00
//
int main()
{
	float a = 8.5f;
	return 0;
}

因為是小端儲存,記憶體中儲存的內容與推斷一致。

E全為0

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

E全為1

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

int main()
{
	int n = 1;//E全為0
	float* pFloat = (float*)&n;
	printf("*pFloat的值為:%.100fn", *pFloat);
	n = -1;//E全為1
	printf("*pFloat的值為:%.100fn", *pFloat);
	return 0;
}

到此這篇關於C語言詳細分析浮點數在記憶體中的儲存的文章就介紹到這了,更多相關C語言浮點數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com