C#-32位和64位上的数学运算结果不一致 [英] C# - Inconsistent math operation result on 32-bit and 64-bit

查看:98
本文介绍了C#-32位和64位上的数学运算结果不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

double v1 = double.MaxValue;
double r = Math.Sqrt(v1 * v1);

r = double.32位计算机上的MaxValue
r = 64位计算机上的Infinity

r = double.MaxValue on 32-bit machine r = Infinity on 64-bit machine

我们在32位计算机上进行开发,因此直到客户通知之前才意识到问题。为什么会发生这种不一致的情况?如何防止这种情况的发生?

We develop on 32-bit machine and thus unaware of the problem until notified by customer. Why such inconsistency happens? How to prevent this from happening?

推荐答案

由于FPU的工作方式,x86指令集存在棘手的浮点一致性问题。内部计算所用的有效位比存储在双精度数中的位高得多,因此当将数字从FPU堆栈刷新到内存时会导致截断。

The x86 instruction set has tricky floating point consistency issues due the way the FPU works. Internal calculations are performed with more significant bits than can be stored in a double, causing truncation when the number is flushed from the FPU stack to memory.

x64 JIT编译器,它使用SSE指令,SSE寄存器的大小为double的大小。

That got fixed in the x64 JIT compiler, it uses SSE instructions, the SSE registers have the same size as a double.

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

This is going to byte you when your calculations test the boundaries of floating point accuracy and range. You never want to get close to needing more than 15 significant digits, you never want to get close to 10E308 or 10E-308. You certainly never want to square the largest representable value. This is never a real problem, numbers that represent physical quantities don't get close.

利用这个机会来找出您的计算出了什么问题。运行客户所使用的相同操作系统和硬件非常重要,这需要很长时间才能获得执行此操作所需的计算机。

Use this opportunity to find out what is wrong with your calculations. It is very important that you run the same operating system and hardware that your customer is using, high time that you get the machines needed to do so. Shipping code that is only tested on x86 machine is not tested.

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

The Q&D fix is Project + Properties, Compile tab, Platform Target = x86.

以前,x86上的不良结果是由JIT编译器中的错误引起的。它生成以下代码:

Fwiw, the bad result on x86 is caused by a bug in the JIT compiler. It generates this code:

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

缺少fmul指令,由代码优化器在发布模式下将其删除。无疑是由它看到double.MaxValue值触发的。那是一个错误,您可以在connect.microsoft.com上报告它。可以肯定的是他们不会修复它。

The fmul instruction is missing, removed by the code optimizer in release mode. No doubt triggered by it seeing the value at double.MaxValue. That's a bug, you can report it at connect.microsoft.com. Pretty sure they're not going to fix it though.

这篇关于C#-32位和64位上的数学运算结果不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆