我的算法正在计算单精度浮点运算的epsilon 。它应该在 1.1921e-007 左右。这是代码:
static void Main(string[] args) {
// start with some small magic number
float a = 0.000000000000000013877787807814457f;
for (; ; ) {
// add the small a to 1
float temp = 1f + a;
// break, if a + 1 really is > '1'
if (temp - 1f != 0f) break;
// otherwise a is too small -> increase it
a *= 2f;
Console.Out.WriteLine("current increment: " + a);
}
Console.Out.WriteLine("Found epsilon: " + a);
Console.ReadKey();
}
在调试模式下,它给出以下合理的输出(缩写):
current increment: 2,775558E-17
current increment: 5,551115E-17
...
current increment: 2,980232E-08
current increment: 5,960464E-08
current increment: 1,192093E-07
Found epsilon: 1,192093E-07
但是,当切换到发布模式时(无论有/无优化!),代码给出以下结果:
current increment: 2,775558E-17
current increment: 5,551115E-17
current increment: 1,110223E-16
current increment: 2,220446E-16
Found epsilon: 2,220446E-16
这对应于double precision的值。所以我假设,一些优化会导致对双精度值进行计算。在这种情况下,结果当然是错误的!
另外:只有在项目选项中以X86 Release 为目标时才会发生这种情况。同样:优化开/关无关紧要。我使用的是 64 位 WIN7,VS 2010 Ultimate,目标是 .NET 4.0。
什么可能导致这种行为?一些WOW问题?如何以可靠的方式绕过它?如何防止 CLR 生成使用双精度而不是单精度计算的代码?
注意:切换到“Any CPU”甚至“X64”作为平台目标是没有选择的——即使这里没有出现问题。但是我们有一些本地库,有不同版本的 32/64 位。所以目标必须是具体的。