为什么将f64转换为u64然后又转换为f64会产生不同的值?

时间:2020-09-01 21:47:16

标签: hash rust key unsafe

我有一个独特的场景,我想使用f64作为HashMap中的键。特别是,我知道f64永远不会是NaN,我可以容忍应该相等但不能相等的f64。所以我transmute()f64u64。但是,当我将u64拔出HashMaptransmute()回到f64时,它是一个不同的值。代码位于playground下方和上方。

use std::collections::HashMap;

fn main() {
    let x = 5.0;
    let y: u64 = unsafe { std::mem::transmute(x) };
    let x: f64 = unsafe { std::mem::transmute(y) };
    println!("y: {}, x: {}", y, x);
    let mut hash = HashMap::new();
    hash.insert(y, 8);
    for (y, _) in &hash {
        let x: f64 = unsafe { std::mem::transmute(y) };
        println!("y: {}, x: {}", y, x);
    }
}

我想念什么?

1 个答案:

答案 0 :(得分:8)

当您写for (y, _) in &hash时,y将成为键的引用,然后您将其转换为无意义的浮点数。

如果您写for (&y, _) in &hash或使用*y,您将获得期望的值。

转变错误的事情就是为什么在使用transmute时永远不要推断类型,而总是避免使用transmute。特别是,对于此特定的转换,有安全的方法f64::to_bitsf64::from_bits。更加惯用的方式是使用HashMap<FloatWrapper, Value>实现FloatWrapper的{​​{1}}。