提问人:Filipe Gonçalves 提问时间:3/27/2015 最后编辑:ShepmasterFilipe Gonçalves 更新时间:12/17/2018 访问量:185
为什么编译器解析源文件中的浮点数的方式与运行时不同?
Why does the compiler parse a floating point number in a source file differently than at runtime?
问:
我最近一直在做一些 Rust 项目来学习语言并获得一些乐趣。我正在 Rust 中编写类似于 libconfig 的东西,使用 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 -> 假
现在,我知道这一定是与臭名昭著的浮点精度问题有关。我知道,即使两个浮点数在打印时可能看起来相同,但由于各种原因,它们可能会有所不同,但我猜想,从中获取浮点数等同于显式声明一个浮点数并将其初始化为 。显然,我错了,但为什么呢?parse::<f32>("X")
X
毕竟,如果我在内部声明并初始化一个浮点数,编译器将不得不执行与生成最终可执行文件时相同的工作。X
parse()
为什么编译器以与运行时函数不同的方式解析源文件中的浮点数?这不应该是一致的吗?我很难解决这个问题!X
parse::<f32>()
答:
5赞
Shepmaster
3/27/2015
#1
请注意,OP 的特定示例不再失败(在 Rust 1.31.0 中测试)
一个已知问题是标准库和 rustc 词法分析器解析浮点值的方式不同。
标准库最终调用from_str_radix,您可以在那里看到实现。我不确定解析浮点数文字的编译器版本的确切位置,但此评论表明它利用了 LLVM:
编译器使用 LLVM 来解析文字,我们不能完全依赖 LLVM 作为我们的标准库。
评论
0赞
Filipe Gonçalves
3/27/2015
这很有意思。我想知道他们是否能以某种方式模仿 LLVM 的行为以使其保持一致。这可能并不容易,但我希望从长远来看,这个问题能得到解决。感谢您的回答!
1赞
Shepmaster
3/27/2015
我认为愿望是这两种实现最终的行为相同。在目前的情况下,也存在一定的性能不足,所以这可能也摆在桌面上。不幸的是,有一个差异的 ULP 可能不是最顶端的。也许您可以了解它并提交补丁!^_^
上一个:平均浮点数时保持精度
评论
{:.20}
u32