Jas*_*son 7 c# c++ floating-point double
我们正在将C++数学库转换为C#.该库混合使用浮点数和双精度数(有时在它们之间进行转换)我们正在尝试做同样的事情,以便在C#中获得与C++中完全相同的结果,但事实证明这是非常困难的,如果不是不可能的话.
我认为问题是以下一个或多个问题,但我不是专家:
将浮点数转换为double和double转换为浮点数会导致不可预测的结果,并在C++和C#中以不同方式完成
C++和C#处理浮点精度的方式不同,它们不能相互模仿
.NET中有一个设置可以使它像C++一样运行,但我找不到它(都是32位)
有人可以向我解释可能存在的问题,也许可以将我与微软的一些权威文档联系起来,我可以用来帮助解释这种情况以及产生差异的原因吗?
编辑
我们使用的是VC6和.NET4.0
由于NDA的原因,我不能举出计算的例子,但我可以为差异显示一些数字......可能它们本身很无用:
8.085004000000000 (C#) vs.
8.084980000000000 (C++)
8.848165000000000 (C#) vs.
8.848170000000000 (C++)
0.015263214111328 (C#) vs.
0.015263900756836 (C++)
Run Code Online (Sandbox Code Playgroud)
应该指出的是,这些数字包括复杂的问题.这些是计算结果.
Pas*_*uoq 10
C++允许程序为临时结果保留比子表达式所暗示的更高的精度.可能发生的一件事是中间表达式(或它们的未指定子集)被计算为扩展的80位浮点数.
另一方面,如果这适用于C#,我会感到惊讶,但即使这样做,C#编译器也不必选择相同的表达式子集来计算为80位扩展浮点数.编辑:请参阅Eric的评论如下.
同一中间精度问题的另一个实例是当编译器使用fmadd指令进行乘法,然后在源代码中添加(如果目标体系结构具有它 - 例如,PowerPC).该fmadd指令准确地计算其中间结果,而正常的加法将对中间结果进行舍入.
为了防止C++编译器这样做,您应该只需要使用volatile变量为中间结果编写浮点计算作为三地址代码.如果此转换更改了C++程序的结果,则意味着上述问题正在发挥作用.但后来你改变了C++方面的结果.在没有读取生成的程序集的情况下,可能无法在C#中获得完全相同的旧C++结果.
如果它有点旧,你的C++编译器也可以优化浮点计算,就好像它们不相关时一样.你无能为力.这是不正确的.三地址代码转换将再次阻止编译器应用它,但同样没有简单的方法让C#编译器重现旧的C++结果.