2012-12-08 54 views
0

假設我想檢查兩個數字ab是否相等。由於浮點不精確,我知道不是簡單地檢查a == b,我通常要挑選一些小號碼eps,而不是檢查abs(a - b) < eps測試時浮點不精確性的帳戶「大約大於」

但是,如果我在檢查a > b時想考慮浮點錯誤,該怎麼辦?我猜測,而不是簡單地

if (a > b) { 
    ... 
} 

我想要做的事,如:

if ((a > b) || abs(a - b) < eps) { 
    ... 
} 

這是正確的嗎?如何檢查a是否「大於」b

+1

「我知道,而不是簡單地檢查== B,我通常要挑一些少量的每股收益」你應該知道的是,你要了解你的程序的邏輯,並利用這些知識來選擇一個合適的ε- ,**如果有需要的話**。相同的理解會導致你對'a> b'做出正確的決定。沒有爲'一== B'沒有通用的解決方案(您可以投訴給誰就給誰告訴你有),並有對'一> B'沒有通用的解決方案。 –

+0

這是不可能回答這樣的問題,不知道更多的應用程序。例如,用'如果(A> B - EPS)',這相當於你的第二個'if'聲明,你會得到一些誤報。如果沒有進一步的信息,那麼這些誤報是否適用於您的特定應用是無法衡量的。 –

+0

使用'epsilon'可能不夠,因爲正確選擇epsilon取決於所涉及的相對大小。深入研究這些問題絕對值得。 [Goldberg的論文](http://www.validlab.com/goldberg/paper.pdf)是一個經典的,重要的理論。還有一系列的文章[這裏](http://randomascii.wordpress.com/category/floating-point/)。 –

回答

2

您在問如何計算來自錯誤輸入(某些值中有錯誤的值)的正確結果(是否一個值大於另一個值)。很顯然,這是不可能的:不正確的輸入會產生不正確的輸出。但是,在某些特定情況下,我們可以挽回一些東西。以下討論一種情況。

讓我們假設你已經計算出了一些ab近似於理想值一個b,其中一個b是,如果計算是用精確的數學做,你將有結果。另外,假定我們知道誤差範圍Ë一個Ë b這樣一個 - Ë一個a一個 + Ë一個一個 - e bbb + e b。換句話說,計算出的ab分別位於ab附近的一些區間內。 (根據所執行的操作,有可能是錯誤可能導致ab趴在一些無關的間隔,甚至可能不包含一個b。但我們會假設你已經「表現良好」的錯誤。)

在這種情況下,如果a - Ë一個>b + è b,那麼可以肯定的是一個>b

但是,假設您測試此條件並返回true(如果它成立)。然後,只要這返回true,您將知道a>b。但是,當它返回false時,您將無法確定a>b是否爲假。所以,如果你想執行一些動作只有當你一定一個>b這個測試是好的。但是這會導致您錯過在某些情況下執行此操作時a>b

假設您不想錯過任何這些情況。再考慮條件a + Ë一個>b - Ë b。如果a>b,則該條件必須爲真。因此,如果您測試此條件並在其執行時執行所需操作,則執行總是時將執行a>b。但是,如果不是這樣的話,也可以執行一些操作a>b

這表明你有選擇。如果你的計算有錯誤,有時你的應用程序會做錯誤的事情。你必須選擇:

  • 它是如何接受的是應用程序執行的操作,當它是假的是一個>b。它總是可接受/不可接受的,還是取決於如何接近ab
  • 對於您的應用程序而言,如果它確實無法執行該操作,那麼該接受程度如何?a>b。它總是可接受/不可接受的,還是取決於如何接近ab

如果你能找到一些令人滿意的妥協,那麼你設置你的病情一些中等水平,和你測試的條件a-b > e,對於一些e是介於 - Ë一個 - Ë b和+ Ë一個 + è b,包括端值。如果您找不到令人滿意的折中方案,那麼您需要改進ab的計算以減少錯誤,或者您需要以某種方式重新設計您的程序。

注意:在這種情況下的最終測試是a-b > e而不是a > b+e,因爲可能會有一個小的舍入誤差計算b+e。還可以有一個舍入誤差計算a-b,但僅當ab並不彼此靠近,在這種情況下的差,即使有舍入,比e大得多(除非你的錯誤間隔是惡劣)。在我們所關心的精確度,當a靠近b的情況下,a-b計算是準確的。