在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)((a-b)/c));
float d = (float)((a-b)/c);
unsigned short result2 = (unsigned short)( d );
输出:
5374, 5375
将
(float)((a-b)/c)
拆分为单独的赋值语句不应影响在启用
strict (/fp:strict)
的情况下的结果。
我认识一个工作在 MSVC 优化器上的人,我会给他发送一个错误报告。
更新:
这是他们的回复:
嗨 Alex,感谢您提供此错误报告。我将尝试在即将发布的 VC++ 版本中修复此问题,但可能无法实现。
顺便说一句,如果你打开 /arch:SSE2 ,这个 bug 就不会重现。由于我们正在默认情况下启用 /arch:SSE2 进行下一个 VC++ 发布(https://connect.microsoft.com/VisualStudio/feedback/details/688736/compiler-generates-sse-instructions-without-arch-sse),所以默认行为将显示该 bug 已经被修复了。 但是,如果您恢复旧的 FP 模型(throw /arch:IA32),则可能仍存在该 bug。
Eric
所以他们已经确认这是一个 bug。
Strict (/fp:strict)
是否确实像代码中所写的那样保证了严格的浮点数,然后再提交报告。这与CLI无关。优化器没有遵守严格的浮点数规则。 - Mysticial