2012-07-10 30 views
15

我有轉換爲雙像這樣的字符串:「-Weverything」屈服「比較==浮點或=不安全!」

double d = [string doubleValue]; 

doubleValue的文件告訴我們,一旦溢出,此方法返回HUGE_VAL-HUGE_VAL。這是我檢查這個早些時候:

if (d == HUGE_VAL || d == -HUGE_VAL) 
    //overflow 

現在,由於加入了新的「-Weverything」警告標誌,則編譯器現在抱怨

Comparing floating point with == or != is unsafe 

我怎樣才能解決這個問題?如何應該我在做這些比較?


我也有關於比較兩個「正常」的浮點數(即不是「HUGE_VAL」的)同樣的問題。例如,

double a, b; 
//... 
if (a != b) //this will now yield the same warning 
    //... 

這應該如何解決?

回答

29

您不必擔心此警告。這在很多情況下都是無稽之談,包括你的。

doubleValue的文檔沒有說它返回的內容足夠接近HUGE_VAL-HUGE_VAL溢出。它表示在溢出的情況下它會返回這些值。

換句話說,在溢出的情況下,方法返回的值將==HUGE_VAL-HUGE_VAL進行比較。

爲什麼警告首先存在?

考慮示例0.3 + 0.4 == 0.7。此示例評估爲false。包括您遇到的警告的作者在內的人們認爲浮點數==是不準確的,並且意外的結果來自這種不準確性。

他們都是錯的。

浮點數此外是「不準確的」,對於某些不準確的意義:它返回您請求的操作的最接近的可表示的浮點數。在上面的例子中,轉換(從十進制到浮點)和浮點加法是奇怪行爲的原因。

浮點數等於另一方面,它的工作方式與其他離散類型完全相同。浮點相等是確切的:除了小的異常(NaN值和+0。和-0。的情況)外,當且僅當所考慮的兩個浮點數具有相同的表示形式時,相等纔會計算爲真。

如果兩個浮點值相等,則不需要一個epsilon來測試。並且,如Dewar says in substance,示例0.3 + 0.4 == 0.7中的警告應該在+上,而不是在==上,警告是有意義的。

最後,在epsilon內比較意味着不相等的值看起來相等,這不適用於所有算法。

+0

有道理。另一方面,在某些方面,似乎也有道理對此提出警告。有什麼辦法可以更明確地告訴編譯器:「是的,我絕對相信我將這些浮點數相互比較,並且不會警告我。」 ?所以在我確定的情況下,警告不會出現。在其他情況下,我會做epsilon測試。 – NoobOverflow 2012-07-10 21:37:53

+0

@NoobOverflow如果你真的想讓編譯器很開心,可以測試'd> = HUGE_VAL || d <= -HUGE_VAL'。它不使用'=='計算相同的東西。但我建議不要使用警告。 – 2012-07-10 21:47:22

+0

@NoobOverflow實際上,我之前的建議使得代碼不易讀,但是如果Objective-C有一個函數「is_infinity」,使用它會使代碼**更具可讀性。該函數的規範應該是它爲'HUGE_VAL'和'-HUGE_VAL'這兩個值準確地返回true,我建議你使用它。 – 2012-07-10 21:58:09

-1

由於浮點類型不準確,不應將浮點數與==或!=進行比較,這可能會導致在使用這些運算符時出現意外錯誤。 您應該測試浮標是否位於彼此的距離內(大多數時候稱爲「Epsilon」)。

它看起來是這樣的:

const float EPSILON = 1.0f; // use a really small number instead of this 

bool closeEnough(float f1, float f2) 
{ 
    return fabs(f1-f2)<EPSILON; 
    // test if the floats are so close together that they can be considered equal 
} 
+1

可以推薦什麼小量?這種方法是否也適用於這些HUGE_VAL?而且,你的答案是否意味着上面的帕斯卡的評論是不正確的? – NoobOverflow 2012-07-10 21:09:20

+0

另外,是否有像我這樣可以使用的很好的內置函數?我很遺憾我必須在全球範圍內把自己的定製功能集中起來。 – NoobOverflow 2012-07-10 21:12:25

+0

帕斯卡是正確的,你可能不需要擔心這個警告。不過有一個內置的epsilon,看看[this](http://www.cplusplus.com/reference/std/limits/numeric_limits/) – Brainbot 2012-07-10 21:58:47

8

在這種情況下,請嘗試使用>=<=

+3

爲什麼這樣更好? – 2012-07-11 17:52:12

+3

好吧,它不會比較嚴格的相等性,所以它會使編譯器更安靜。由於沒有什麼可以比HUGE_VAL大或小於-HUGE_VAL,它的工作原理是一樣的。 – echristopherson 2012-07-11 18:31:57

2

如果你確信你比較,你要告訴它鐺,環繞與您的代碼:

#pragma clang diagnostic ignored "-Wfloat-equal" 
/* My code triggering the warnings */ 
#pragma clang diagnostic pop