C# - 32位和64位的数学运算结果不一致

dav*_*led 11 c#

请考虑以下代码:

double v1 = double.MaxValue;
double r = Math.Sqrt(v1 * v1);
Run Code Online (Sandbox Code Playgroud)

r = double.MaxValue在32位机器上r = 64位机器上的无穷大

我们在32位机器上开发,因此在客户通知之前不会发现问题.为什么会发生这种不一致?如何防止这种情况发生?

Han*_*ant 21

由于FPU的工作方式,x86指令集具有棘手的浮点一致性问题.使用比存储在double中更高位的内部计算执行内部计算,从而将数字从FPU堆栈刷新到内存时导致截断.

在x64 JIT编译器中修复了它,它使用SSE指令,SSE寄存器的大小与double相同.

当您的计算测试浮点精度和范围的边界时,这将打字.你永远不想接近需要超过15位有效数字,你永远不想接近10E308或10E-308.你当然不想想象最大的可表示价值.这绝不是一个真正的问题,代表物理量的数字不会接近.

利用这个机会找出你的计算有什么问题.运行与客户正在使用的操作系统和硬件相同的操作系统和硬件非常重要,这样您就可以获得所需的机器.仅在x86计算机上测试的运输代码未经过测试.

Q&D修复程序是Project + Properties,Compile选项卡,Platform Target = x86.


Fwiw,x86上的错误结果是由JIT编译器中的错误引起的.它生成此代码:

      double r = Math.Sqrt(v1 * v1);
00000006  fld         dword ptr ds:[009D1578h] 
0000000c  fsqrt            
0000000e  fstp        qword ptr [ebp-8] 
Run Code Online (Sandbox Code Playgroud)

缺少fmul指令,代码优化器在发布模式下删除了该指令.毫无疑问,它看到了double.MaxValue的价值.这是一个错误,您可以在connect.microsoft.com上报告.很确定他们不会修复它.

  • @Jonners:很有意思. (7认同)