问题描述
这真是一个奇怪的错误给我,我花了很长时间才弄明白发生了什么。为了简化问题和繁殖,使用VS2005只需要创建一个空的Win32控制台应用程序,并在主方法使用code:
This is really a weird bug to me and it took me long time to figure out what's happening. To simplify things and reproduce, just create a empty win32 console application using VS2005 and use this code in the main method:
float a = 411.00418f;
float b = 1.0f;
float c = 0.076279849f;
unsigned short result = (unsigned short)( (a-b)/c );
unsigned short result2 = (unsigned short)( (float)((a-b)/c) );
// Debug: 5374, 5375
// Release: 5374, 5374
printf("%d, %d\n", result, result2);
为什么RESULT2显示在调试/释放模式不同的价值?
Why result2 shows different value in debug/release mode?
推荐答案
在MSVC,默认的浮点模式为 precise(/ FP:precise)
。这意味着优化可能会做一定的优化,以提高精确度和性能。
In MSVC, the default floating-point mode is precise (/fp:precise)
. Meaning that the optimizer may do certain optimizations to improve accuracy or performance.
试着改变模式以严格的(/计划生育:严格)
。这将使编译器遵循四舍五入并且这种严格的浮点规则。
Try changing mode to strict (/fp:strict)
. This will make the compiler follow the strict floating-point rules on rounding and such.
(编辑:严格的(/计划生育:严格)
似乎并没有在这种情况下工作... ...)
( strict (/fp:strict)
doesn't seem to work in this case...)
如果你看一下优化构建的拆解,可以看到整个计算被折叠和优化了。
If you look at the disassembly of the optimized build, you can see that the entire computation has been folded and optimized out.
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
编辑:这看起来像一个编译器优化的错误给我
在严格的(/计划生育:严格)
,以下code产生不同的结果:
Under strict (/fp:strict)
, the following code produces different results:
float a = 411.00418f;
float b = 1.0f;
float c = 0.076279849f;
unsigned short result1 = (unsigned short)((float)((a-b)/c));
float d = (float)((a-b)/c);
unsigned short result2 = (unsigned short)( d );
输出:
5374, 5375
拔出(浮点)((AB)/ C)
到一个单独的转让不应影响下严格的(/ FP结果:严格)
。
Pulling out the (float)((a-b)/c)
into a separate assignment should not affect the results under strict (/fp:strict)
.
我知道是谁在MSVC优化工作的家伙之一。我会发送错误报告给他。
下面是他们的回应:
亚历克斯您好,感谢这个bug报告。我会尽力解决这个问题的
即将到来的VC ++版本,但可能无法做到这一点。
FWIW,错误不一样,如果你把/拱门重现:SSE2,因为我们
默认情况下,下一个VC ++版本SSE2:正在启用/弓
(https://connect.microsoft.com/VisualStudio/feedback/details/688736/compiler-generates-sse-instructions-without-arch-sse).
FWIW, the bug doesn’t reproduce if you throw /arch:SSE2, and since we are enabling /arch:SSE2 by default for the next VC++ release (https://connect.microsoft.com/VisualStudio/feedback/details/688736/compiler-generates-sse-instructions-without-arch-sse).
因此,默认行为将表明,这个错误是固定的。但是,如果
您恢复到旧型号FP(抛出/弓:IA32)的错误可能
还是present。
So, the default behavior will show that this bug is fixed. But if you revert back to the old FP model (throw /arch:IA32) the bug may still be present.
埃里克
所以,他们确认这是一个错误。
这篇关于为什么浮动计算和铸造显示不同的结果在调试和发布配置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!