我有一个为x86平台目标配置的c#项目。该应用程序在WinXP中运行良好,但在Win7中出现问题。我用的是VS2008。
请参阅下面的测试代码(问题:WinXP打印0,Win7打印1)。
注意:如果在调试模式下运行或添加一行跟踪,代码在Win7中也可以正常工作。
请告知,谢谢!
using System;
using System.Windows.Forms;
namespace Hello
{
public partial class MainForm : Form
{
public MainForm()
{
//The problem: it shows "0" in WinXP, and shows "1" in Win7
MessageBox.Show(Test.GetValue().ToString());
Environment.Exit(0);
}
}
public class Test
{
static int a = 0;
static public float GetValue()
{
float b = 0.8149883f;
float x = (696f / b + a);
//Note: it returns 0 if uncomments the line below, otherwise it returns 1
//MessageBox.Show("hello");
return (x - (int)x);
}
}
}
除了@CodeInChaos所指出的这一点之外,浮点计算在不同的硬件架构上也是不同的。这就是浮点单位的本质。即使两个FP单元都遵循IEEE754,也会产生不同的结果。显然,这些差异将会微乎其微。因此,即使没有JIT差异,您也可能在不同的机器上看到不同的结果。
在您的情况下,您只需要以不同的方式比较浮点值。与其检验是否完全相等,不如检验是否在一个很小的公差范围内相等,例如abs(a-b)<epsilon
,其中epsilon
是一个很小的数字。
JIT编译器可以自由地优化浮点数,即使这稍微改变了结果。你不能指望所有平台的结果都是一样的。
有时它将您的853.9999...
解释为854.0
有时它将其保留为853.9999...
。这是因为在某些平台上,中间结果的计算精度更高。在什么时候分解为float
是不同的。在您的示例中,看起来消息框强制编译器将值存储在FPU之外,此时它被转换为32位浮点数。
如果性能不太重要,您可以简单地使用Decimal
并获得确定性结果。
请注意,如果使用double,结果会像预期的那样工作。
如果您取除法的结果并查看IEEE-754中浮点数和双精度表示的表示,您就会明白为什么:
853.99998993850586566702859415282As float: 854.00000
As double: 853.99998993850590
从http://babbage.cs.qc.edu/courses/cs341/ieee(html) - 754.
为什么你在调试和发布之间看到不同的结果,我不确定-我在VS2010中没有看到。