为什么浮动计算和转换在调试和发布配置中显示不同的结果?

这对我来说真的是一个奇怪的错误,我花了很长时间才弄清楚发生了什么。 为了简化和重现,只需使用VS2005创建一个空的win32控制台应用程序,并在main方法中使用此代码:

float a = 411.00418f; float b = 1.0f; float c = 0.076279849f; unsigned short result = (unsigned short)( (ab)/c ); unsigned short result2 = (unsigned short)( (float)((ab)/c) ); // Debug: 5374, 5375 // Release: 5374, 5374 printf("%d, %d\n", result, result2); 

为什么result2在调试/释放模式下显示不同的值?

在MSVC中,默认浮点模式是precise (/fp:precise) 。 意味着优化器可以进行某些优化以提高准确性或性能。

尝试将模式更改为strict (/fp:strict) 。 这将使编译器遵循舍入等严格的浮点规则。

(编辑: strict (/fp:strict)似乎在这种情况下不起作用……)

如果您查看优化构建的反汇编,您可以看到整个计算已折叠并优化。

 push 5374 ; 000014feH push 5374 ; 000014feH push OFFSET ??_C@_07MHMABKGB@?$CFd?0?5?$CFd?6?$AA@ call DWORD PTR __imp__printf add esp, 12 ; 0000000cH 

编辑:这对我来说看起来像编译器优化器错误。

strict (/fp:strict) ,以下代码产生不同的结果:

 float a = 411.00418f; float b = 1.0f; float c = 0.076279849f; unsigned short result1 = (unsigned short)((float)((ab)/c)); float d = (float)((ab)/c); unsigned short result2 = (unsigned short)( d ); 

输出:

 5374, 5375 

(float)((ab)/c)拉出到单独的赋值中不应该影响strict (/fp:strict)下的结果。


我知道其中一个从事MSVC优化工作的人。 我会向他发送一份错误报告。

更新:

这是他们的回应:

嗨亚历克斯,谢谢你的错误报告。 我将尝试为即将推出的VC ++版本修复此问题,但它可能无法实现。

FWIW,如果你抛出/ arch:SSE2,并且因为我们在下一个VC ++版本中默认启用/ arch:SSE2,所以bug不会重现(https://connect.microsoft.com/VisualStudio/feedback/details/688736 /编译器生成-SSE-指令,而无需拱-SSE)。

因此,默认行为将显示此错误已得到修复。 但是如果你恢复到旧的FP模型(throw / arch:IA32),bug仍然可能存在。

埃里克

所以他们已经证实这是一个错误。