繁体   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