Floating point 为什么编译器在源文件中解析浮点数的方式与在运行时不同?

Floating point 为什么编译器在源文件中解析浮点数的方式与在运行时不同?,floating-point,rust,precision,floating-accuracy,floating-point-conversion,Floating Point,Rust,Precision,Floating Accuracy,Floating Point Conversion,我最近一直在做一些Rust项目来学习语言并获得一些乐趣。我正在写一些类似于Rust的东西,使用板条箱生成解析器 在过去的一个小时里,我一直在与一个奇怪的bug作斗争,在这个bug中,从一个示例配置文件解析的一些值与预期值不符 最终,我将缺陷缩小为: fn main() { let my_flt = "10.4e-5".parse::<f32>().unwrap(); let other_flt = 10.4e-5; println!("{} == {} -&g

我最近一直在做一些Rust项目来学习语言并获得一些乐趣。我正在写一些类似于Rust的东西,使用板条箱生成解析器

在过去的一个小时里,我一直在与一个奇怪的bug作斗争,在这个bug中,从一个示例配置文件解析的一些值与预期值不符

最终,我将缺陷缩小为:

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);
}
fn main(){
让我的_flt=“10.4e-5”。解析::()。展开();
设其他_flt=10.4e-5;
println!(“{}={}->{}”,my_flt,other_flt,my_flt==other_flt);
}
令人惊讶的是,这张照片显示:

0.000104==0.000104->false

现在,我知道这一定与过去臭名昭著的浮点精度问题有关。我知道,即使两个浮点在打印时看起来相同,但由于各种原因,它们的比较可能会有所不同,但我猜想,从
parse::(“X”)
获取浮点相当于显式声明并将浮点初始化为
X
。很明显,我错了,但为什么

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


为什么编译器在源文件中以与运行时解析函数不同的方式解析float
X
?这不应该是一致的吗?我很难把这件事做完

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


标准库和rustc lexer解析浮点值的方式不同,这是一个很好的例子

标准库最终调用了,您可以在那里看到实现。我不确定编译器版本解析浮点pint文本的确切位置,但指出它利用了LLVM:

编译器使用LLVM解析文本,我们不能完全依赖LLVM作为标准库


以更高的精度打印(例如,
{.20}
),很明显它们是不同的;转换为
u32
检查字节,是的,第一个是0x38da1a92,第二个是0x38da1a93。正如结果所预期的那样,尾数变化了一个。@MatthieuM。说得好。移动并更新了更多的信息。这很有趣。我想知道他们是否能以某种方式模仿LLVM的行为,从而使其保持一致。这可能没那么容易,但我希望从长远来看这会得到解决。谢谢你的回答!我认为希望这两个实现最终的行为是相同的。在目前的情况下,还存在一定的性能不足,因此这可能也是摆在桌面上的问题。不幸的是,拥有一个不同的ULP可能不是最重要的。也许你可以了解它的所有信息并提交补丁^_^