簡體   English   中英

浮點數的Java哈希碼

[英]java hashcode for floating point numbers

我想使用Double (或Float )作為Hashmap

Map<Double, String> map = new HashMap<Double, String>()
map.put(1.0, "one");
System.out.println(map.containsKey(Math.tan(Math.PI / 4)));

這將返回false。

如果我比較這兩個數字,我會做這樣的事情

final double EPSILON = 1e-6;
Math.abs(1.0 - Math.tan(Math.PI / 4)) < EPSILON

但是由於Hashmap將使用hashcode因此對我來說很Hashmap

我想實現一個roundKey函數,在將它用作鍵之前將其四舍五入到EPSILON倍數

map.put(roundKey(1.0), "one")
map.containsKey(roundKey(Math.tan(Math.PI / 4)))
  • 有沒有更好的辦法 ?
  • 什么是實現此roundKey的正確方法

如果您知道合適的舍入方法,則可以使用它。 例如,如果需要四舍五入到美分,則可以四舍五入到小數點后兩位。

但是,對於上面的示例,將離散舍入到固定精度可能不合適。 例如,如果四舍五入到小數點后六位,則即使相差<< << 1e-6,1.4999e-6和1.5001e-6也不會匹配,因為一個向上舍入而另一個向下舍入。

在這種情況下,您最能做的就是使用NavigableMap

NavigableMap<Double, String> map = new TreeMap<>();

double x = ....;
double error = 1e-6;

NavigableMap<Double, String> map2 = map.subMap(x - error, x + error);

或者你可以使用

Map.Entry<Double, String> higher = map.higherEntry(x);
Map.Entry<Double, String> lower = map.lowerEntry(x);
Map.Entry<Double, String> entry = null;
if (higher == null)
    entry = lower;
else if (lower == null)
    entry = higher;
else if (Math.abs(lower.getKey() - x) < Math.abs(higher.getkey() - x))
    entry = lower;
else
    entry = higher;
// entry is the closest match.
if (entry != null && Math.abs(entry - x) < error) {
    // found the closest entry within the error
}

這將找到連續范圍內的所有條目。

最好的方法是不要使用浮點數作為鍵,因為它們(如您所發現的)不會進行比較。
Kludgy的“解決方案”就像在它們彼此處於一定范圍之內時稱它們相同,只會在以后導致問題,因為您要么不得不拉伸過濾器,要么使過濾器的時間變得更加嚴格,兩者都會導致潛在的問題與現有的代碼,和/或人們會忘記事情應該如何工作。
當然,在某些應用程序中您想這樣做,但是作為查找內容的關鍵嗎? 不。您最好使用角度(以度為單位)和整數(如此處的鍵)。 如果需要大於1度的精度,請通過存儲0到3600之間的數字來使用角度(例如十分之一度)。
這將為您提供可靠的Map行為,同時保留您計划存儲的數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM