IEEE 浮點表示
Microsoft Visual C++ 與 IEEE 數值標準一致。 實數有三種內部變化。 在 Visual C++ 中是使用 real*4 和 real*8。 Real*4 是使用 float 一詞宣告。 Real*8 是使用 double 一詞宣告。 在 Windows 32 位元程式設計中,long double 資料型別對應至 double。 不過,組合語言支援使用 real*10 資料型別的計算。
值將以下列方式儲存:
值 |
儲存成 |
---|---|
real*4 |
正負號位元,8 位元指數,23 位元尾數 (Mantissa) |
real*8 |
正負號位元,11 位元指數,52 位元尾數 |
real*10 |
正負號位元,15 位元指數,64 位元尾數 |
在 real*4 和 real*8 格式中,尾數有一個假定的前置數字 1 未儲存在記憶體,因此該尾數實際上是 24 或 53 位元 (雖然僅儲存 23 或 52 位元)。 實際則以 real*10 格式儲存此位元。
指數被偏移了其最大值的一半。 這表示實際的指數是從儲存的指數減去此偏移值得來。 如果儲存的指數小於偏移值,則它實際上是負指數。
指數的偏移值如下:
指數 |
偏移值 |
---|---|
8 位元 (real*4) |
127 |
11 位元 (real*8) |
1023 |
15 位元 (real*10) |
16383 |
這些指數不是 10 的次方,而是 2 的次方。 也就是說,以 8 位元儲存的指數最多可達 127。 2**127 的值大約等於 real*4 實際限制的 10**38。
尾數儲存成 1.XXX.. 格式的二進位小數。 . 二進位小數的值大於等於 1 且小於 2。 請注意,實數永遠是以正規化格式儲存;也就是說,尾數會向左移位 (Left Shift),使得尾數的高位元永遠為 1。 由於這個位元永遠為 1,因此在 real*4 和 real*8 格式中它已被內定 (並未儲存)。 二進位 (非十進位) 的小數點被假設為就在前置數字 1 的右邊。
因此,各種大小的格式如下:
格式 |
BYTE 1 |
BYTE 2 |
BYTE 3 |
BYTE 4 |
... |
BYTE n |
---|---|---|---|---|---|---|
real*4 |
SXXX XXXX |
XMMM MMMM |
MMMM MMMM |
MMMM MMMM |
|
|
real*8 |
SXXX XXXX |
XXXX MMMM |
MMMM MMMM |
MMMM MMMM |
... |
MMMM MMMM |
real*10 |
SXXX XXXX |
XXXX XXXX |
1MMM MMMM |
MMMM MMMM |
... |
MMMM MMMM |
S 代表正負號位元,X 等為指數位元,M 等為尾數位元。 請注意,最左邊的位元被假設為 real*4 和 real*8 格式,但在 real*10 格式的 BYTE 3 中顯示為 "1"。
若要正確地移位二進位小數點,您必須先還原指數的偏移,然後將二進位小數點向右或向左移動適當的位元數。
範例
以下是一些 real*4 格式的範例:
在下例中,正負號位元為零,儲存的指數為 128 或 100 0000 0 (二進位),其為 127 加 1。 儲存的尾數為 (1.) 000 0000 ... 0000 0000,其中包括進位的前置數字 1 和二進位小數點,因此實際的尾數為 1。
SXXX XXXX XMMM MMMM ... MMMM MMMM 2 = 1 * 2**1 = 0100 0000 0000 0000 ... 0000 0000 = 4000 0000
與 +2 相同,不過已設定正負號位元。 所有 IEEE 格式的浮點數也都是如此。
-2 = -1 * 2**1 = 1100 0000 0000 0000 ... 0000 0000 = C000 0000
相同的尾數;指數增加 1 (偏移值為 129 或二進位的 100 0000 1)。
4 = 1 * 2**2 = 0100 0000 1000 0000 ... 0000 0000 = 4080 0000
相同指數;尾數增加一半,即 (1.) 100 0000 ...0000 0000,其為 1 1/2 (小數數值為 1/2、1/4、1/8 等等),因為這是二進位小數。
6 = 1.5 * 2**2 = 0100 0000 1100 0000 ... 0000 0000 = 40C0 0000
與其他 2 的次方相同的指數,尾數為 127 (2 的次方) 減 1,或二進位的 011 1111 1。
1 = 1 * 2**0 = 0011 1111 1000 0000 ... 0000 0000 = 3F80 0000
偏移的指數為 126 或二進位的 011 1111 0,而尾數為 (1.) 100 0000 ... 0000 0000,其為 1 1/2。
.75 = 1.5 * 2**-1 = 0011 1111 0100 0000 ... 0000 0000 = 3F40 0000
與 2 完全相同,除了代表 1/4 的位元是設定於尾數。
2.5 = 1.25 * 2**1 = 0100 0000 0010 0000 ... 0000 0000 = 4020 0000
1/10 是二進位的一種循環小數。 尾數僅有 1.6,而偏移的指數意指 1.6 要除以 16 (即二進位的 011 1101 1,十進位為 123)。 真正的指數為 123 – 127 = –4,其表示要乘積的因數為 2**–4 = 1/16。 請注意,儲存的尾數在最後一個位元會進位,嘗試盡可能精確地表示無法表示的數字 (無法以二進位精確地表示 1/10 和 1/100 的原因與無法以十進位表示 1/3 的原因類似)。
0.1 = 1.6 * 2**-4 = 0011 1101 1100 1100 ... 1100 1101 = 3DCC CCCD
0 = 1.0 * 2**-128 = all zeros--a special case.