2016-02-22 38 views
1

我有一些項目有一個id和一個值,我正在尋找最大的元素。在float比較中處理等於case

值是浮動/雙打,並作爲領帶打破我想用較小的id對象。

一種方法如下:

double maxValue = Double.NEGATIVE_INFINITY; 
Item maxItem = null; 
for (Item item : items) { 
    if (item.value() > maxValue) { 
     maxValue = item.value(); 
     maxItem = item; 
    } else if (item.value() == maxValue && item.id() < maxItem.id()) { 
     maxItem = item; 
    } 
} 

然而,這包括使用浮點數的質量比較,這是氣餒,在我的情況還創建代碼分析步驟的一個關鍵問題。

當然,我可以寫些東西來避免這個問題,例如,使用>=進行第二次比較,但從可讀性的角度來看,我未來的我或任何其他讀者可能會懷疑它是否是一個錯誤。

我的問題:是否有一種方法可以很好地表達意圖,並避免使用==進行此項任務的float比較?

+0

你可以只添加註釋,你的代碼解釋給你的未來的自己或別人誰定定地看着你的代碼在將來。 – Jesper

+4

很明顯,這不是「浮動平等FUD」所警告的情況。 – harold

+0

問題到底是什麼?你在找什麼說「好吧,這兩個花車不是真的平等,但他們足夠接近」? – Tunaki

回答

0

在這種情況下,測試兩個浮點值的相等性沒有任何問題。兩個浮點/雙精度值可以相等,並且可以使用==運算符進行測試。

對浮點值不鼓勵使用==的一個原因是,將它們與文字常量進行比較可能會導致意外的行爲,因爲文字通常以十進制表示法編寫,而浮點變量則以二進制格式存儲。並非所有十進制值都可以用二進制精確表示,因此變量的值僅爲十進制值的近似值。例如:3.0 * 0.1 == 0.3的計算結果爲false。

另一個原因是浮點值並不總是表現爲實數。特別是,浮點運算不一定是可交換的(x * y == y * x)和關聯((x * y) * z == x * (y * z))。例如,(0.3 * 0.2) * 0.1 == 0.3 * (0.2 * 0.1)評估爲false。

然而在你的情況下,沒有理由不使用==

+0

並不意見不一,但也有其他原因:即使沒有文字,兩個計算結果在flo中預期會產生相同的結果,但在浮點數上通常是不同的。這個原因也很有趣,因爲如果沒有它,我們可能會決定不寫錯誤的文字並解決問題,但這還不夠。 – harold

+0

@harold謝謝,我將其納入答案。 – Hoopje

0

你可以寫一個Comparator<Item>,然後用它來尋找最大的項目:

Comparator<Item> byValueAscThenIdDesc = (i1, i2) -> { 
    int valueComparison = Double.compare(i1.value(), i2.value()); 
    if(valueComparison == 0) { 
     int idComprison = Integer.compare(i1.id(), i2.id()); 
     return -idComparison; 
    } 
    return valueComparison; 
}; 

List<Item> items = new ArrayList<>(); 

Item max = items.stream().max(byValueAscThenIdDesc).get();