I want to use Double (or Float) as keys in a Hashmap
Map<Double, String> map = new HashMap<Double, String>()
map.put(1.0, "one");
System.out.println(map.containsKey(Math.tan(Math.PI / 4)));
and this returns false.
if I were comparing these two numbers I would have done something like this
final double EPSILON = 1e-6;
Math.abs(1.0 - Math.tan(Math.PI / 4)) < EPSILON
But since Hashmap would use hashcode it breaks things for me.
I thought to implement a roundKey function that rounds to some multiple of EPSILON before using it as a key
map.put(roundKey(1.0), "one")
map.containsKey(roundKey(Math.tan(Math.PI / 4)))
roundKeyIf you know what rounding is appropriate, you can use that. e.g. if you need to round to cents, you can round to two decimal places.
However, for the example above discrete rounding to a fixed precision might not be appropriate. e.g. if you round to 6 decimal places, 1.4999e-6 and 1.5001e-6 will not match as one rounds up and the other down even though the difference is << 1e-6.
In that situation the closest you can do is to use a NavigableMap
NavigableMap<Double, String> map = new TreeMap<>();
double x = ....;
double error = 1e-6;
NavigableMap<Double, String> map2 = map.subMap(x - error, x + error);
or you can use
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
}
This will find all the entries within a continuous range.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With