2014-11-25 65 views
4

我寫了這個功能,圓單打整數:使用上證所一輪德爾福

function Round(const Val: Single): Integer; 
begin 
    asm 
    cvtss2si eax,Val 
    mov Result,eax 
    end; 
end; 

它的工作原理,但我需要改變舍入模式。顯然,根據this,我需要設置MXCSR寄存器。

如何在Delphi中執行此操作?

我這樣做的原因首先是我需要「離開零」舍入(就像在C#中),即使通過SetRoundingMode也是不可能的。

+0

爲什麼downvote? – IamIC 2014-11-25 11:32:23

+2

你不需要'mov Result,eax'。結果**是** eax。其實'功能圓形(const Val:單一):整數; asm cvtss2si eax,Val end;'夠了;) – 2014-11-25 17:09:45

+0

謝謝。這回答了另一個問題。 – IamIC 2014-11-25 17:25:47

回答

8

在現代Delphi上,要設置MXCSR,您可以撥打System單位的SetMXCSR。要讀取當前值,請使用GetMXCSR

小心SetMXCSR,就像Set8087CW不是線程安全的。儘管我努力說服Embarcadero改變這種情況,但似乎這種特殊的設計缺陷將永遠留在我們身邊。

在舊版Delphi上,您使用LDMXCSRSTMXCSR操作碼。你可以寫自己的版本是這樣的:

function GetMXCSR: LongWord; 
asm 
    PUSH EAX 
    STMXCSR [ESP].DWord 
    POP  EAX 
end; 

procedure SetMXCSR(NewMXCSR: LongWord); 
//thread-safe version that does not abuse the global variable DefaultMXCSR 
var 
    MXCSR: LongWord; 
asm 
    AND  EAX, $FFC0 // Remove flag bits 
    MOV  MXCSR, EAX 
    LDMXCSR MXCSR 
end; 

這些版本是線程安全的,我希望將編譯並運行在老德爾福版本。

請注意,爲您的功能使用名稱Round可能會造成很多混淆。我會建議你不要這樣做。

最後,我檢查了英特爾文檔,並且英特爾浮點單元(x87,SSE)都提供了IEEE754標準規定的舍入模式。它們是:

  • 四捨五入至最近的(甚至)
  • 回合下來(-∞朝)
  • 四捨五入(朝向+∞)
  • 回合向零(截斷)

所以,你想要的舍入模式不可用。

+0

我正在使用Delphi 7. – IamIC 2014-11-25 11:38:36

+0

謝謝。我在內部稱之爲「TrueRound」。你寫的與我已有的相似。我希望爲此使用SSE。 – IamIC 2014-11-25 11:42:09

+1

我已經調整了我的'SetMXCSR'的線程安全版本,所以我認爲它可以在D7中工作。我手邊沒有D7。 Q中的代碼在D6中編譯。所以你應該很好走。 – 2014-11-25 11:44:45