1. 摘要

在瞭解到C語言中整型是以二進位制補碼形式儲存在記憶體中後,我們不禁很好奇:那麼浮點型的資料是以什麼形式儲存在記憶體中的呢?

實際上,早在1985年,電氣電子工程師學會就制定了IEEE 754標準來解決單精度浮點數在計算機記憶體中的儲存問題。

那麼接下來,我們就以IEEE754-1985版來看一看浮點數在記憶體中的真實面目。

2. 浮點數的表達方式

2.1 浮點數的組成

浮點型家族中包含有:float、double、long double型別

IEEE 754標準下,一個浮點數V可以被拆解成三個部分

V = (-1) ^ S * f * 2 ^ E
  1. 1-bit sign S ------ 符號位S,用來表示正負
  2. Biased exponent e = E+bias:指數位,負責浮點數的大小
  3. Fraction f = · b1b2 … bp−1:小數位,負責浮點數的精度,且f大於等於1小於2

2.2 單精度浮點數

對於32位的單精度浮點數而言,記憶體中32個bit位是這樣分配的:

  1. 1位符號位
  2. 8位指數位
  3. 23位小數位

2.3 雙精度浮點數

對於64位的雙精度浮點數而言,記憶體中64個bit位是這樣分配的:

  1. 1位符號位
  2. 11位指數位
  3. 52位小數位

2.4 指數偏差(Biased Exponent)

2.4.1指數E不為全0或全1

對於float型,我們發現8位的E如果就表示8個無符號的二進位制位,那麼指數位2^E只能表示比1大的數,而不能表示0-1之間的數,這就導致負指數沒法被表示出來。

為了表示負指數,規定E在記憶體中的值等於你想要真實表達的指數的值再加上中間數127(對於double型,這個中間數是1023),所以即使你想使用負指數,加上127後E也還是非負的。

這就叫“指數偏差”。

2.4.2 指數位E全為1

1)小數位 f 不全為0

無論符號位s是什麼,浮點數V代表NaN

NaN 是 Not a number 的意思,代表了一個無法被表示出來的值,比如一個數除以0或負數的平方根

2)小數位 f 全為0

浮點數V = ( −1)s∞,此時表示正負無窮大

2.4.3 指數位E全為0

以下用單精度浮點數為例:

1)小數位 f 不全為0

V = (−1)s * 2−126 * (0.f)

2)小數位 f 全為0

V = (−1)s * 0 ,此時V表示正負0

2.5 小數位的規定(fraction)



小數位 f 是一個 [1,2) 間的數,所以 f 可以寫成以上圖片中的形式:1.xxxxx

由於 f 的第一位總是1,所以我們將第一位的1省略,這樣就能多表示一位小數點之後的數了

2.6 浮點數的範圍

浮點數的所能表達的最大值/最小值被定義在了標頭檔案<float.h>中

對於float型:

最小:2-126= 1.175×10-38

最大:2128 = 3.403×1038

對於double型:

最小:2-1022= 2.225×10-308

最大:21024 = 1.798×10308

3. 程式碼分析

讓我們來看一段程式碼來進行具體分析

#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;
}

那麼執行結果是什麼呢?

不急,我們先對程式碼進行一波分析。

第一步

我們建立了一個int型變數n並賦值為9

第二步

我們將一個float型的指標變數pfloat指向了n

那我們就要問了:整型9在記憶體中是怎麼儲存的呢?

當然是以補碼形式儲存,所以這記憶體中的32個位元位是:

00000000 00000000 00000000 00001001

第三步

我們以%d(有符號整型)形式對上述32個位元位進行列印,顯然螢幕上應輸出:

n的值為:9

第四步

我們以%f(float型)形式對上述32個位元位進行列印

再看這32個位元位

00000000 00000000 00000000 00001001

我們重拾這個公式:V = (-1) ^ S * f * 2 ^ E 與 這張圖:



重新將上述32個位元位排序

0 00000000 00000000000000000001001

故 V = (−1)s * 2−126 * (0.00000000000000000001001)2,是一個很小很小的數,所以螢幕上預設列印小數點後六位的話,應輸出:

*pFloat的值為:0.000000

第五步

將pfloat指向地址的內容修改為9.0,顯然此時上述32個位元位中儲存的是單精度浮點數的二進位制表達方式,遵循IEEE 754標準

(9.0)10 = (1001.0)2 = (1.0010 * 23)2

所以上述32個位元位此時應該是:

0 10000010 00100000000000000000000

第六步

我們以%d(有符號整型)形式對上述32個位元位進行列印,顯然螢幕上應輸出:

num的值為:1,091,567,616

第七步

我們以%f(float型)形式對上述32個位元位進行列印,顯然螢幕上應輸出:

*pFloat的值為:9.000000

執行截圖如下:

4.參考文獻

1.IEEE Standard 754 Floating Point Numbersgeeksforgeeks

2.IEEE 754-1985Wikipedia

3.Single-precision floating-point formatWikipedia

4.IEEE Standard for Binary Floating-Point Arithmetic. 1985. doi:10.1109/IEEESTD.1985.82928. ISBN 0-7381-1165-1.

5.NaN,Wikipedia

注:來自維基百科參考文獻的快照若有需要,請聯絡本人

感謝你們的閱讀!本人水平有限,如有錯誤,還望指正!