为什么将 f64 转换为 u64 然后再转换回 f64 会导致不同的值?

HiD*_*der 3 hash unsafe key rust

我有一个独特的场景,我想在其中f64用作HashMap. 特别是我知道f64永远不会NaN并且我可以容忍f64应该相等但不是。所以,我transmute()f64u64。然而,当我拉u64出来HashMaptransmute()这回f64它是一个不同的值。下面和操场上的代码。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

mca*_*ton 8

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

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

转换错误的事情是为什么在使用时永远不应该推断类型transmute,并且应该始终避免transmute. 特别是,对于这个特定的转换,有安全方法f64::to_bitsf64::from_bits. 一种更惯用的方法是使用HashMap<FloatWrapper, Value>where FloatWrapperimplements Ord