2012-01-02 81 views
2

我正在尋找一個強大的Java地圖,其中密鑰查找將考慮到雙精度有限(大約1e-15或1e-16)。我在哪裏可以找到這樣的事情?健壯的地圖<Double, sth> in Java

編輯:遵循喬恩的建議我認爲這將有助於定義等價。一個想法是將這些數字集中到十五個最相關的十進制數字。其他數字將被舍入(以任何一致的方式 - 最快執行)。這有意義嗎?什麼是最好的實施?

+0

雙重的關鍵?真? – 2012-01-02 14:27:38

+2

您需要更加精確地滿足您的要求。特別是,如果你正在尋找類似「近似等價」的事情,最終會變得棘手,因爲地圖假設如果A和B相等,而B和C相等,則A和C必須相等。這在近似等價的情況下效果不佳。 – 2012-01-02 14:28:08

+0

'健壯'我想你想要在1e-15或每個左右的兩個鍵被視爲相同的鍵? – 2012-01-02 14:29:58

回答

4

恕我直言,最好的辦法是在添加或查找值之前對值進行規範化。例如通過使用舍入。

BTW:您可以使用TDoubleObjectHashMap,它支持自定義散列策略並使用原始雙鍵。

6

我建議你使用TreeMap並實現你自己的自定義比較器,比較兩個double值並考慮到所需的精度。

4

我並不完全確定你需要什麼,但是你可以在Double上實現一個包裝並覆蓋它的hashCode()equals()方法來滿足你的「有限精度」查找。因此,任何Map實現都將是健壯的,因爲它依靠hashCode()equals()進行密鑰查找。

當然,您的地圖將以Map<DoubleWrapper, smth>的形式出現。

+0

我如何知道哪個Double鍵「關閉」,而無需將其與映射中已經存在的每個雙鍵進行比較? – 2012-01-02 14:33:38

+0

您的hashCode()函數應該返回所有「關閉」雙精度的相同哈希碼。同樣等於()應該對那些「接近」雙打說真。無需比較地圖中的所有雙打。 – 2012-01-02 14:36:01

+0

毫無疑問,它可以,但它並不像看起來那麼容易,因爲Jon Skeet和Mitch Wheat在評論中指出了這個傳遞特性。 – 2012-01-02 14:41:32

0

總結的答案和上述評論,我結束了以下包裝(這可能不處理NaN的大氣壓):

public static class DoubleWrapper { 
    private static final int PRECISION = 15; 
    private final Double roundedValue; 

    public DoubleWrapper(double value) { 
     final double d = Math.ceil(Math.log10(value < 0 ? -value: value)); 
     final int power = PRECISION - (int) d; 

     final double magnitude = Math.pow(10, power); 
     final long shifted = Math.round(value*magnitude); 
     roundedValue = shifted/magnitude; 

    } 

    public double getDouble() { 
     return roundedValue; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     return roundedValue.equals(obj); 
    } 

    @Override 
    public int hashCode() { 
     return roundedValue.hashCode(); 
    } 
}