文章編號: 126455 - 上次校閱: 2003年12月9日 - 版次: 2.0

如何避免四捨五入的溢位 probs Pentium 處理器上的 (& I)

系統提示本文適用於您使用的作業系統之外的作業系統。與您不相關的文章內容已停用。

在此頁中

全部展開 | 全部摺疊

結論

Intel 公司已經識別在 Pentium 處理器浮點值轉換為整數數字時使用浮動點整數儲存庫 (徒手) 指令與相關的兩個次要錯誤。這些錯誤牽涉到的窄範圍的浮點數的界限的例外狀況處理和牽涉到在六個特定運算元的兩個捨入模式未預期的行為。程式設計人員可以輕鬆地解決第一個 Bug 檢查之前,轉換值的範圍。程式設計人員可以不覆寫預設值捨入模式來避免第二個 Bug。

其他相關資訊

不同的程式語言不同的方式處理從浮點轉換為整數。C、 C + + 和 FORTRAN 程式都是最有可能是安全 ; 也就是它們是不可能會受到不需要明確修改的捨入模式程式設計人員。基本的程式是比較容易受到 Bug。

應用程式的一般都不會受到影響。應用程式應包括適當的錯誤檢查,並採取適當動作,以從例外狀況復原。若要執行此動作的應用程式需要執行明確檢查之前要轉換的範圍,或是實作明確的例外處理。如果應用程式依賴明確的例外處理,遇到 Bug 的可能性存在。使用例外處理的語言所撰寫的應用程式很可能使用範圍檢查,從而允許應用程式效能的理由是無核取選項以編譯。

徒手概觀

徒手指令用來將浮點數轉換為帶正負號的整數。當一個整數變數指派浮點數一的 C 或 FORTRAN 程式中,例如值的值必須被截斷為整數之前被儲存。從浮點整數其他轉換也可能會出現 ; 基本和 Pascal 命名法,例如圓形代替截斷小數部分。

徒手指令操作其中四種四捨五入模式: 看 (也稱為截斷),最接近 (最接近或偶數),向上和向下。預設型別轉換,藉由 C 和 FORTRAN 使用捨入模式,看而 Basic 是使用最接近。處理器指出輸入的運算元是整數的整數位數 (PE) 的例外狀況旗標。PE 旗標設定為 true 時如果要轉換數字已不是整數,也就是它具有小數部分。它是不變否則。捨入效果捨入的方向 (C1) 旗標] 所示。如果輸入的值捨入成一個具有更大的大小過於分散,設定 C1 旗標 ; 否則已清除。

徒手將浮點數轉換為 16、 32 或 64 位元帶正負號的整數。 因為範圍的浮點數大於這些格式的任何部分浮點數無法轉換成整數。比方說最大的 16 位元整數是 32767,所以嘗試將 32768.5 轉換為 16 位元的整數會導致例外狀況 (在此情況下,操作不正確的例外狀況 (IE))。例外狀況的處理由例外狀況遮罩] 中浮動控制點控制暫存器。如果設定了無效的作業的例外狀況遮罩遮罩的例外狀況,否則遮罩。

比方說在 Microsoft Windows 版本 3.1 下執行的應用程式的開頭被遮罩的所有浮動點例外狀況。不同的應用程式可能會變更例外狀況遮罩,並提供它們自己的方法處理例外狀況。例如 Microsoft Visual C++ 設定操作不正確的例外狀況遮罩,同時保留被遮罩的精確度例外狀況。在 C + + 中開發的應用程式將會看到當徒手指令嘗試轉換超出界限,數字,除非變更例外處理時,會出現一個快顯視窗。

未偵測到的溢位

Intel 已識別 Bug 中徒手指示轉換浮點數字到任一 16 或 32 位元帶正負號的整數。64 位元整數會儲存在 FISTP 指令並不會受到影響。錯誤會發生於捨入模式設定為接近 」 或是 「 啟動 」 (Up 一個有限範圍內的浮動點值不足的界限的區域中。這個範圍不論例外狀況] 遮罩請 0 值寫入記憶體]、 PE 旗標已設定]、 不設定 IE 旗標,引發沒有 IE 例外狀況]。

在下面的圖表浮動自 A 的點值而 B 可以轉換成整數。此範圍以外的值應該引發例外狀況。這個 Bug 會影響 C 和 D 範圍只中的值。

16 位元徒手
                                                 65535.5 -
          -32768.5     0      32767.5            65536.0
<-------------[--------|--------]-------------------|-------->
   overflow       Normal Range        overflow
              A                 B                   C

32-Bit FIST
                                                          4,294,967,295.5 -
      -2,147,483,648.5     0      2,147,483,647.5         4,294,967,296.0
<-------------[------------|------------]-----------------------|-------->
   overflow           Normal Range             overflow
              A                         B                       D
				

比方說需要 32 位元帶正負號整數,例如 4,294,967,295.7 範圍之外的許多。這是以數學方式四捨五入為 4,294,967,296。 因為以這個 Bug Pentium 處理器不會引發例外狀況以這個數字。它只是寫入一個 0 到記憶體並不會將控制傳輸至處理常式或引發 IE 旗標。

使用 Microsoft Visual Basic 的應用程式

Microsoft Visual Basic 會自動將提升處理混合的類型作業的資料型別。這可以避免許多情況下的則溢位條件。例如:
   IntX = SngY*IntZ
   IntX = 65535.7*2
				

不過,隱含轉換可能會受到影響。下列的 Visual Basic 3.0 版程式碼會產生不同的結果取決於處理器:
   Dim X As Integer
   Dim Y As Single
   Y = 65535.5
   X = Y
   MsgBox Cstr(X)
				

上述程式碼應該產生執行階段錯誤 6 「 溢位 」 的訊息。在 Pentium 處理器架構機器上, 這段程式碼會導致傳回零 (0)。 若要避免這個錯誤的簡單方法是在您的程式碼中包含範圍檢查。 例如:
   If (x)>=65535.5
   Then Error 6
				

唯一受影響的程式會是那些明確設陷錯誤 6 (溢位) 和牽涉到是明確的工作分派的浮點運算式為整數資料型別或長整數資料型別或明確轉換的浮點點使用 CInt() 或 CLng() 的運算式。

採用明確的界限檢查以防止溢位條件的程式應該不會受到影響。

如果範圍檢查造成不利影響效能在迴圈中的,將程式碼移轉到 C 語言動態連結程式庫 (DLL) 可能是好的選項。

程式結果

在組件] 層級建議的解決方法就是前面徒手指令 FRNDINT (浮動點圓為整數) 指令的插入。FRNDINT 會正確地來回浮點點值之前執行徒手指令 (相對於 FISTP) ; 校正文字也會需要保留其輸入。未來版本的 Visual Basic 將包含此修正程式。

注意: 會強制處理器以模擬浮動點指示任何方法可避免在效能降低和速度的代價問題。

捨入模式錯誤

六個特定運算元徒手指示的結果會是未如預期般運作。有所有四種四捨五入模式中的旗標差異。也是被儲存在 「 向上 」 及 「 關閉 」 捨入模式數目不正確的可能性。在最近"和"chop"捨入最常使用的模式儲存記憶體值是正確的。16-、 32-和指令的 64 位元變種會影響這個 Bug。

下表顯示受影響數字捨入模式和預期和實際的值:
   Operand     | Rounding | Exp. | Actual | Exp. | Actual | Exp. | Actual
(any one of)   |  mode    | mode |  mode  |  PE  |   PE   |  C1  |   C1
-----------------------------------------------------------------------
1/16 (0.0625)  |  nearest |  0   |   0    |   1  |  unch. |  0   |   0
1/8 (0.125)    |   chop   |  0   |   0    |   1  |  unch. |  0   |   0
3/16 (0.1875)  |   down   |  0   |   0    |   1  |  unch. |  0   |   0
               |    up    |  1   |   0    |   1  |  unch. |  1   |   0
-1/16 (-0.0625)|  nearest |  0   |   0    |   1  |  unch. |  0   |   0
-1/8 (-0.125)  |   chop   |  0   |   0    |   1  |  unch. |  0   |   0
-3/16 (-0.1875)|   down   | -1   |   0    |   1  |  unch. |  1   |   0
               |    up    |  0   |   0    |   1  |  unch. |  0   |   0
				

六個的數字 (1/16、 1/8、 3/16-1/16,-1/8,和-3/16),則可能發生不正確的結果。在所有的捨入模式下 PE 旗標是不一致地有發生圓 ; 它會保持不變。內向上"捨入模式三個的正數數值,徒手儲存不正確的值 (而非 1 的 0) ; 同樣地,"向下 」 的捨入模式中,三個負數,徒手提供不正確的結果 (0-1 代替)。在每一個這種情況下 C1 元也設定不正確。不過,最近"和"chop"捨入模式,儲存至記憶體值都是正確,C1 元原狀。

程式結果

當捨入模式設定為 「 向上"或"向下 」 時,只會傳回不正確的結果,從第二個 Bug。因此,它應該不會影響應用程式除非明確地從語言預設值變更捨入模式的應用程式。如果一個應用程式變更 「 向上 」 或 「 關閉 」 捨入模式,它不再可以依賴語言提供 floating-point-值-至-整數-號碼轉換設施,必須提供自己的例如使用 FRNDINT。

不正確的狀態資訊中會影響所有此 PE 旗標捨入模式,應該在大部份的應用程式不顯著。如果捨入發生 PE 旗標已經設定。PE 例外狀況也通常被遮罩。因此不正確的值是不顯著例外處理常式只會使用 C1 位元。

因應措施

在組件層級的第二個徒手 Bug 建議的解決方法是相同的第一個 ; 插入 FRNDINT 指令前面徒手指令。

應用程式的程式設計人員可以避免四捨五入藉由不覆寫預設值捨入模式的第二個 Bug 中的錯誤。

注意: 強制處理器以模擬浮動點指示任何方法可避免兩個問題在效能降低和速度的代價。

這篇文章中的資訊適用於:
  • Microsoft Visual Basic 2.0 Standard Edition
  • Microsoft Visual Basic 3.0 Professional Edition
  • Microsoft Visual Basic 2.0 Professional Edition
  • Microsoft Visual Basic 3.0 Professional Edition
關鍵字:?
kbmt KB126455 KbMtzh
機器翻譯機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:126455? (http://support.microsoft.com/kb/126455/en-us/ )
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。
Retired KB Article依現狀不再更新的知識庫內容免責聲明
本文旨在說明 Microsoft 不再提供支援的產品。因此,本文係依「現狀」提供,不會再更新。