floating-point - 为什么编译器解析源文件中的 float 与运行时不同?

标签 floating-point rust precision floating-accuracy floating-point-conversion

我最近一直在从事一些 Rust 项目,以学习这门语言并享受一些乐趣。我正在写类似libconfig的东西在 Rust 中,使用 peg用于生成我的解析器的 crate 。

在过去的一个小时里,我一直在与一个奇怪的错误作斗争,其中从示例配置文件中解析的一些值与预期值不相等。

最终,我将错误范围缩小到:

fn main() {
    let my_flt = "10.4e-5".parse::<f32>().unwrap();
    let other_flt = 10.4e-5;
    println!("{} == {} -> {}", my_flt, other_flt, my_flt == other_flt);
}

令人惊讶的是,这会打印:

0.000104 == 0.000104 -> false

See it in the playground

现在,我知道这必须与臭名昭著的旧浮点精度问题有关。我知道即使两个 float 在打印时可能看起来相同,但由于各种原因它们可以进行不同的比较,但我猜想从 parse::<f32>("X") 获取 float 相当于显式声明并将 float 初始化为 X 。显然,我错了,但为什么呢?

毕竟,如果我声明并将 float 初始化为 X ,在内部,编译器必须执行与 parse() 相同的工作生成最终可执行文件时。

编译器为什么解析 float X以与运行时不同的方式在源文件中 parse::<f32>()功能?这不应该是一致的吗?我很难把这件事结束!

最佳答案

请注意,OP 的具体示例不再失败(在 Rust 1.31.0 中测试)


这是一个 known issue标准库和 rustc 词法分析器以不同的方式解析浮点值。

标准库最终调用 from_str_radix ,您可以在那里看到实现。我不确定解析 float-pint 文字的编译器版本到底在哪里发生,但是 this comment表明它利用 LLVM:

The compiler uses LLVM to parse literals and we can’t quite depend on LLVM for our standard library.

关于floating-point - 为什么编译器解析源文件中的 float 与运行时不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29291500/

相关文章:

c++ - 空间中的旋转 vector 和 C++ 中的高精度

python - 字符串转 float 错误

java - Math.nextUp(arg) 始终与 arg + Math.ulp(arg) 相同吗?

rust - 当 self 可变时返回可变引用,否则引用

multithreading - 在多个线程中改变共享可变变量

sql - 确定列上使用的最大小数位数

c - 通过快速浮点倒数高效计算 2**64/除数

c++ - 为什么 printf 和 isnan 不同意 long double 值是否为 NaN?

regex - 花式正则表达式创建多个匹配项

math - float 学有问题吗?