我最近一直在从事一些 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
现在,我知道这必须与臭名昭著的旧浮点精度问题有关。我知道即使两个 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/