【问题标题】:C++ / C# differences with float and doubleC++ / C# 与 float 和 double 的区别
【发布时间】:2010-08-26 23:41:29
【问题描述】:

我们正在将 C++ 数学库转换为 C#。该库混合使用浮点数和双精度数(有时在它们之间进行转换),我们正在尝试做同样的事情,以便在 C# 中获得与在 C++ 中完全相同的结果,但事实证明即使不是不可能也非常困难.

我认为问题是以下一项或多项,但我不是专家:

  1. 将浮点数转换为双精度浮点数和双精度浮点数会导致不可预测的结果,并且在 C++ 和 C# 中的处理方式不同

  2. C++ 和 C# 处理浮点精度的方式不同,它们不能互相模仿

  3. .NET 中有一个设置可以让它像 C++ 一样运行,但我找不到它(两者都是 32 位)

有人可以向我解释可能存在的问题,或者将我链接到 Microsoft 的一些权威文档,我可以用来帮助解释情况和差异的原因吗?

编辑
我们正在使用 VC6 和 .NET4.0

由于保密协议的原因,我无法给出计算示例,但我可以显示一些数字来表示差异......它们本身可能非常无用:

 8.085004000000000 (C#) vs. 
 8.084980000000000 (C++)    

 8.848165000000000 (C#) vs. 
 8.848170000000000 (C++)   

 0.015263214111328 (C#) vs. 
 0.015263900756836 (C++)  

应该注意,这些数字包括复合问题。这些是计算的结果。

【问题讨论】:

  • 你能提供一个具体的例子来说明你有不同的结果吗?
  • 我认为这更多地与硬件有关而不是语言(尽管我可能是错的)。浮点寄存器大于内存位置(在英特尔上)。因此,如果在寄存器中评估整个表达式,您会得到一个结果,而如果将临时值存储在内存中,您将失去一些精度并获得稍微不同的结果。此外,C++ 编译器可能使用通用浮点运算,而 .NET JIT 编译器可能能够利用一组对体系结构更具体和准确的指令。
  • @Martin 谢谢。那么,是预计 100% 准确,还是预计两者之间存在差异?
  • 浮点运算没有任何事情是 100% 准确的。

标签: c# c++ floating-point double


【解决方案1】:

C++ 允许程序为临时结果保留比子表达式类型所暗示的更高的精度。可能发生的一件事是中间表达式(或它们的未指定子集)被计算为扩展的 80 位浮点数。

另一方面,如果这适用于 C#,我会感到惊讶,但是即使是这样,C# 编译器也不必选择相同的表达式子集来计算为 80 位扩展花车。编辑:请参阅下面 Eric 的评论。

More details

同样的中间精度问题的另一个例子是编译器在源代码中使用fmadd 指令进行乘法和加法运算(如果目标体系结构有它,例如PowerPC)。 fmadd 指令精确计算其中间结果,而正常的加法会将中间结果四舍五入。

为防止 C++ 编译器这样做,您只需将浮点计算编写为三地址代码,使用 volatile 变量作为中间结果。如果这种转换改变了 C++ 程序的结果,就意味着上面的问题在起作用。但是你已经改变了 C++ 端的结果。如果不读取生成的程序集,可能无法在 C# 中获得完全相同的旧 C++ 结果。

如果它有点旧,您的 C++ 编译器还可以优化浮点计算,就好像它们不是关联的一样。您对此无能为力。这是不正确的。三地址代码转换将再次阻止编译器应用它,但同样没有简单的方法让 C# 编译器重现旧的 C++ 结果。

【讨论】:

  • 谢谢。 C++ 是 VC6,而 C# 是使用 C# 是 .NET 4.0
  • 关于您的第二段,我建议您参考 C# 规范的第 4.1.6 节,该节开始 **浮点运算可以以比运算结果类型更高的精度执行。例如,一些硬件架构支持比 double 类型具有更大范围和精度的“扩展”或“long double”浮点类型,并使用这种更高精度类型隐式执行所有浮点运算。 ... ** 有关详细信息,请参阅规范。
  • @Eric 感谢您提供信息。令我惊讶的是,微软在其规范中包含了这一警告,因为当大多数处理器开始在 .NET 上工作时,我会认为大多数处理器都有带有“真实”双精度的 SSE 指令集。例如,Java 对浮点计算有更多保证(Kahan 与人合着了一篇关于该主题的整篇文章,即这种严格性会阻止一些优化,因此被误用。我从来不知道他会站在哪一​​边:)跨度>
  • 请记住,.NET 可以在很多不同的平台上运行,从嵌入式设备到高端服务器,再到运行 Silverlight 的 mac Web 浏览器。处理器确实没有共同点。有关更多问题,请参阅例如 *.com/questions/2342396/…