rust - 有没有办法从 `f64::from(0.23_f32)` 得到 0.23_f64?

标签 rust floating-point

我正在尝试将两个软件结合在一起:一个给我 f32 ,还有一个期望 f64值。在我的代码中,我使用 f64::from(my_f32) ,但在我的测试中,我比较了结果,我比较的值没有按预期转换:f64 value 有一堆额外的、更精确的数字,因此值不相等。

在我的例子中,值为 0.23 .有没有办法转换 0.23_f32f64这样我最终得到 0.23_f64而不是 0.23000000417232513

fn main() {
    let x = 0.23_f32;
    println!("{}", x);
    println!("{}", f64::from(x));
    println!("---");

    let x = 0.23_f64;
    println!("{}", x);
    println!("{}", f64::from(x));
}

Playground


编辑:我知道 float 的存储方式不同——事实上,我使用 this handy visualizer有时查看 32 位和 64 位 float 之间的表示差异。我想看看是否有一些聪明的方法来解决这个问题。


编辑 2:我刚刚想到的一个“聪明”示例是 my_32.to_string().parse::<f64>() --这让我明白了0.23_f64 ,但(显然)需要字符串解析。我认为可能至少有一些与数字相关的东西(因为缺少更好的术语)。

最佳答案

评论已经指出了为什么会这样。这个答案的存在是为了给你提供规避这种情况的方法。

第一个(也是最明显的)是使用任意精度的库。使用rust 的一个很好的例子是 rug .这允许您准确地表达几乎任何数字,但它会导致一些跨 FFI 边界的问题(在其他情况下)。

第二个是做大多数人围绕 float 所做的事情,并将等式括起来。因为您知道大多数 float 不会被准确存储,并且您知道您的输入类型,所以您可以使用诸如 std::f32::MIN 之类的常量。将您的类型括起来,像这样 ( playground ):

use std::cmp::PartialOrd;
use std::ops::{Add, Div, Sub};
fn bracketed_eq<
    I,
    E: From<I> + From<f32> + Clone + PartialOrd + Div<Output = E> + Sub<Output = E> + Add<Output = E>,
>(
    input: E,
    target: I,
    value: I,
) -> bool {
    let target: E = target.into();
    let value: E = value.into();
    let bracket_lhs: E = target.clone() - (value.clone() / (2.0).into());
    let bracket_rhs: E = target.clone() + (value.clone() / (2.0).into());
    bracket_lhs >= input && bracket_rhs <= input
}

#[test]
fn test() {
    let u: f32 = 0.23_f32;
    assert!(bracketed_eq(f64::from(u), 0.23, std::f32::MIN))
}

其中很大一部分是样板文件,其中很多都被编译器完全优化掉了;也可以删除 Clone通过限制某些特征选择来满足要求。 Add , Sub , Div有没有操作,From<I>实现转换,From<f32>对于常量 2.0 .

关于rust - 有没有办法从 `f64::from(0.23_f32)` 得到 0.23_f64?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58174531/

相关文章:

string - 预期结构 `std::string::String`,找到结构 `std::str::Split`

rust - 将属性应用于宏扩展

c++ - 如果我在 x86_64 上使用 gcc 4.9,__float128 到底是什么?

delphi - 如何处理浮点溢出?

C - float 序列化( float 、 double )

multithreading - 接收器在尝试通过 channel 发送时关闭并返回 SendError

rust - 在当前范围内找不到类型 *mut Y 的名为 X 的方法

assembly - 为什么 rust 在有和没有 pub 和 #[no_mangle] 的情况下会产生完全不同的 assembly ?

c - 在不同环境下 C 中使用的 float 范围是多少?

c - 将浮点变量中的逗号分隔字符串写入串行端口