2016-12-06 97 views
1

關於浮點數比較有大量的文檔和討論。但是對於我來說,目前尚不清楚能否保證直接比較數字在所有編譯器和平臺上都能正常工作?精確值的雙/浮點比較

double x = 1.; 
if (1. == x) 
{ 
    //do something 
} 

我們總是會輸入if塊嗎?

編輯:

這裏什麼比較正確的是(永久有效)?這一個?:

double x = 1.; 
if (std::abs(1. - x) < std::numeric_limits<double>::epsilon()) 
{ 
    //do something 
} 
+4

一些浮點值,例如'1.0',可以用IEEE浮點格式(這是最常用的格式)精確表示。所以你的比較可以在你顯示的確切代碼中正常工作。但是,嘗試在'x'上執行一些操作,*應該*將其保留爲'1.0',然後重試比較,並且很可能不起作用。 –

+0

聽起來像你應該閱讀這個:https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html –

+0

爲了解決你的問題的第二部分,不,'std :: numeric_limits : :epsilon()'不打算像那樣使用。 'std :: numeric_limits :: epsilon()'是格式精度的度量,它不是前面計算精度的度量。如果前面的計算可能產生了0.125的絕對誤差,並且您希望在數學計算產生1.0時檢測出沒有誤報的測試,請使用std :: abs(1.x)<= 0.125'。在所有情況下,無論上下文如何,RHS都沒有可用的神奇價值。 –

回答

0

如果你有兩個精確的浮點值,你不必擔心,比較它們可能會違反你的期望。問題是你怎麼知道你的價值觀是確切的?

對於所提供的例子,你可以非常有信心x == 1.0將評估爲true - 我個人不會考慮支持,將不能在該測試的任何平臺。然而,如果不能確切地告訴你應該停止依賴比較的結果,那麼就有可能逐漸複雜化你的例子。

1

是的,像這樣的直接比較 - 無需干預操作 - 將始終有效。爲浮點文字存儲的位模式是浮點系統可以表示的最接近的模式(幾乎總是IEEE-754)。所以測試1.0 == 1.0將始終工作,因爲位模式是1.0;和0.3 == 0.3始終工作,因爲在兩種情況下,位模式 - 儘管不完全是0.3 - 是最接近0.3的表示數。

至於epsilon的東西,遠離機器epsilon,直到你真正知道它代表什麼和它是什麼。機器epsilon是相對的,不是絕對的;並用它來比較「足夠接近」需要了解各種操作可能引入多少錯誤。有趣的是,在你的具體情況下,這兩個測試實際上是相同的:只有正好1.0才能通過測試。