【发布时间】:2017-01-30 23:47:39
【问题描述】:
我想使用HashMap<f64, f64> 来保存已知 x 和键 y 的点到另一个点的距离。 f64 在这里值不重要,重点应该放在关键上。
let mut map = HashMap<f64, f64>::new();
map.insert(0.4, f64::hypot(4.2, 50.0));
map.insert(1.8, f64::hypot(2.6, 50.0));
...
let a = map.get(&0.4).unwrap();
由于f64 既不是Eq 也不是Hash,而只是PartialEq,f64 不足以作为密钥。我需要先保存距离,但也需要稍后通过 y 访问距离。 y 的类型需要是浮点精度,但如果不适用于f64,我将使用具有已知指数的i64。
我尝试了一些技巧,使用我自己的struct Dimension(f64),然后通过将浮点数转换为String,然后对其进行散列来实现Hash。
#[derive(PartialEq, Eq)]
struct DimensionKey(f64);
impl Hash for DimensionKey {
fn hash<H: Hasher>(&self, state: &mut H) {
format!("{}", self.0).hash(state);
}
}
这似乎很糟糕,两种解决方案,我自己的结构或浮点数作为具有基数和指数的整数似乎都非常复杂。
更新:
我可以保证我的密钥永远不会是NaN,或者一个无限值。另外,我不会计算我的密钥,只会遍历它们并使用它们。因此,0.1 + 0.2 ≠ 0.3 的已知错误应该没有错误。
How to do a binary search on a Vec of floats? 和这个问题的共同点是实现浮点数的全序和相等,区别仅在于散列或迭代。
【问题讨论】:
-
您真的需要按精确距离获取对象吗?使用浮点数作为键与测试两个是否相等(确实会发生舍入错误)一样糟糕。
-
@Shepmaster:这里可能存在
f64没有实现Eq的问题,但我认为问题更深层次=> 即使您排除NaN,比较两个浮点数是否相等只是自找麻烦。 -
您希望您的密钥有任何重复值吗?是否有必要通过哈希映射对它们进行重复数据删除?
标签: floating-point hashmap rust