2011-05-24 66 views
23

我們面臨的問題與數據類型雙比較:如何在delphi中比較double?

if(p > pmax) then 
begin 
    Showmessage(''); 
end 

如果兩個值100(P = 100和PMAX = 100),那麼也則如果子句中去。

+0

我不認爲這是一個循環。 – Simon 2011-05-24 14:01:59

+0

@Simon:有一個德國網站http://if-schleife.de/。 [Google翻譯製作](http://translate.google.de/translate?js=n&prev=_t&hl=de&ie=UTF-8&layout=2&eotf=1&sl=de&tl=en&u=http%3A%2F%2Fif-schleife.de% 2F)'沒有if循環,但只有當if語句!'。 – 2011-05-25 12:05:31

回答

10

比較雙打有幾個問題。一個問題是,你看到的不完全是你四捨五入的結果。你可以有99.999999996423和100.00000000001632,它們都舍入到100,但它們不相等。

解決方案是使用一個邊距,以便如果兩個雙倍的差值位於邊距內,您接受它們的平均值。

可以創建使用餘量作爲可選的參數的函數ISEQUAL:

function IsEqual(const ANumber1, ANumber2: Double; const AMargin: Double = cMargin): Boolean; 
begin 
    Result := Abs(ANumber1-ANumber2) <= AMargin; 
end; 
+9

請注意,您的正確解決方案已在Math.pas中作爲'SameValue'提供。 – 2011-11-02 14:11:53

54

的Math.pas單元包括諸如SameValue(),IsZero(),選擇compareValue(),其處理浮動型比較和平等。

const 
    EPSILON = 0.0000001; 
begin  
    if CompareValue(p, pMax, EPSILON) = GreaterThanValue then 
    ShowMessage('p greater than pMax'); 

GreaterThanValue在Types.pas定義

如果你比較你不應該使用一個常量小量非常大的價值,而不是你的小量值應根據計算你正在比較的值。

var 
    epsilon: double; 
begin  
    epsilon := Max(Min(Abs(p), Abs(pMax)) * 0.000001, 0.000001); 
    if CompareValue(p, pMax, epsilon) = GreaterThanValue then 
    ShowMessage('p greater than pMax'); 

請注意,如果您使用CompareValue(a, b, 0)或XE2後來CompareValue(a, b),Delphi會自動在一個良好的小量你填寫。

從德爾福Math單位:

function SameValue(const A, B: Extended; Epsilon: Extended): Boolean; 
begin 
    if Epsilon = 0 then 
    Epsilon := Max(Min(Abs(A), Abs(B)) * ExtendedResolution, ExtendedResolution); 
    if A > B then 
    Result := (A - B) <= Epsilon 
    else 
    Result := (B - A) <= Epsilon; 
end; 

德爾福XE2的現在有重載所有這些功能不需要的ε參數,而是計算出一個適合你(類似傳球epsilon的0值)。爲了清晰的代碼,我建議調用這些更簡單的函數,並讓Delphi處理epsilon。

不使用不帶epsilon參數的重載的唯一原因是性能至關重要,而您希望避免重複計算epsilon的開銷。

+3

+1 for CompareValue – RRUZ 2011-05-24 05:55:19

+0

非常感謝..看起來這是工作..昨天我已經試過這個,但我不知道Types.pas .. – SSE 2011-05-24 06:43:50

+0

-100使用固定值的epsilon,我編輯了答案,而不是解決這個問題。 – Johan 2011-05-24 11:02:13