建議使用 Visual Studio 2017

IEEE 浮點表示

 

如需 Visual Studio 2017 的最新文件請參閱 Visual Studio 2017 文件

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 1BYTE 2BYTE 3BYTE 4...BYTE n
real*4SXXX XXXXXMMM MMMMMMMM MMMMMMMM MMMM
real*8SXXX XXXXXXXX MMMMMMMM MMMMMMMM MMMM...MMMM MMMM
real*10SXXX XXXXXXXX XXXX1MMM MMMMMMMM 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.

浮點數會失去精確度的原因

顯示: