为什么将 f64 转换为 u64 然后再转换回 f64 会产生不同的值?
Why does transmuting a f64 into u64 and then back into f64 result in a different value?
我有一个独特的场景,我想使用 f64
作为 HashMap
中的键。特别是我知道 f64
永远不会是 NaN
并且我可以容忍 f64
应该相等,但不是。所以我transmute()
把f64
改成了u64
。但是,当我将 u64
拉出 HashMap
并将 transmute()
拉回 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);
}
}
我错过了什么?
当您编写 for (y, _) in &hash
时,y
将成为对键的 引用 ,然后您会将其转换为无意义的浮点数。
你应该写 for (&y, _) in &hash
还是使用 *y
,你会得到预期的值。
转换错误的东西是为什么在使用 transmute
时永远不应该推断类型,并且应该始终避免 transmute
。特别是,对于这个特定的转换,有安全方法 f64::to_bits
and f64::from_bits
。一种更惯用的方法是使用 HashMap<FloatWrapper, Value>
其中 FloatWrapper
实现 Ord
.
我有一个独特的场景,我想使用 f64
作为 HashMap
中的键。特别是我知道 f64
永远不会是 NaN
并且我可以容忍 f64
应该相等,但不是。所以我transmute()
把f64
改成了u64
。但是,当我将 u64
拉出 HashMap
并将 transmute()
拉回 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);
}
}
我错过了什么?
当您编写 for (y, _) in &hash
时,y
将成为对键的 引用 ,然后您会将其转换为无意义的浮点数。
你应该写 for (&y, _) in &hash
还是使用 *y
,你会得到预期的值。
转换错误的东西是为什么在使用 transmute
时永远不应该推断类型,并且应该始终避免 transmute
。特别是,对于这个特定的转换,有安全方法 f64::to_bits
and f64::from_bits
。一种更惯用的方法是使用 HashMap<FloatWrapper, Value>
其中 FloatWrapper
实现 Ord
.