【发布时间】:2014-11-07 21:44:37
【问题描述】:
平台:使用 Visual Studio 2013 的 C#。
我有一个在 64 位 Haswell CPU 上运行的 Windows 应用程序,它在启用“首选 32 位”的情况下正常工作。我决定通过取消选择“首选 32 位”来升级到“首选 64 位”,应用程序的算法突然变为不正确的值。 我丢失了 29 位算术精度(这是我对双精度浮点尾数和单精度浮点尾数大小差异的估计)。这里的算术精度差异很大!
C# 代码……测试用例:
using System;
class lngfltdbl
{
static void Main()
{
long lng = 2026872;
float flt = 0.3F;
double dbl = lng + flt;
Console.WriteLine(dbl);
}
}
预期结果(在选择“首选 32 位”时看到):
dbl == 2026872.30000001
(PERFECT! CORRECT to 14 decimal places)
获得的结果(在取消选择“首选 32 位”时看到):
dbl == 2026872.25
(ERROR! CORRECT to 7 DECIMAL PLACES ONLY!)
请注意:过去我对隐式转换很满意,因为“首选 32 位”始终了解如何正确组合不同精度的值。
【问题讨论】:
-
我想指出您的
lng + flt表达式是自找麻烦 - 您不应该在没有明确转换的情况下混合类型(正如 Microsoft 回答所暗示的那样)。我不认为所有大写字母都值得小心。 -
请将其改写为问答。你可以回答你自己的问题!这是一个非常有趣且相当奇怪的观察结果,我认为它会对网站做出重大贡献。
-
@GregRos 我觉得问题应该是“编译器选项可以有功能效果吗?”答案是“是的,很明显。事实上,对于没有功能效果的编译器来说,这是例外而不是规则。例如,GCC 的
-mfpmath=387[GCC 中与问题中讨论的选项最接近的等效项] 改变了生成代码的语义”。如果这在 C# 中没有正确记录,它应该是针对 C# 文档的错误报告,如果是,这只是一个“duh”评论,而不是一个很大的贡献。 -
我正在按照建议进行更改,但无法添加我从 Microsoft 的 JIT 编译器团队收到的答案。 (我最初不想分开答案,因为我不打算为此获得任何功劳)
标签: c# visual-studio-2013 floating-point