我有一个软件项目,在这个项目中,我有时会从小而简单的浮点运算中得到奇怪的结果。我想我漏掉了一些东西,想知道一些关于如何调试以下问题的提示:
(使用的编译器是MS VC 6.0,即Microsoft C编译器的第12版)
第一个异常:
extern double Time, TimeStamp, TimeStep; // History terms, updated elsewhere
void timer_evaluation_function( ) {
if ( ( Time - TimeStamp ) >= TimeStep ) {
TimeStamp += TimeStep;
timer_controlled_code( );
}
{....}
由于某种原因,计时器求值失败,且计时代码从未执行。在调试器中,可以看到trig条件实际上是真的,但fpu拒绝找到肯定的结果。下面的代码段虽然执行了相同的操作,但没有问题。这个问题通过插入一个可以允许失败的虚假评估而得以回避。
我猜fpu的状态会受到之前执行的操作的影响,而且有一些编译器标志会有帮助吗?
第二个异常:
double K, Kp = 1.0, Ti = 0.02;
void timed_code( ){
K = ( Kp * ( float ) 2000 ) / ( ( float ) 2000 - 2.0F * Ti * 1e6 )
{....}
结果是ind,即使调试器将公式计算为大约0.05。使用fld指令将2.0f值加载到fpu时,ind值出现在fpu堆栈中。前一条指令使用fild指令将整数值2000加载为双浮点数。一旦fpu堆栈包含ind值,all将丢失,但调试器再次对公式求值没有问题。稍后,这些操作将返回预期结果。
另外,fpu问题再次出现在函数调用之后。是否应在每个新函数后插入清除FPU状态的浮点操作?是否有编译器标志会以某种方式影响FPU?
我很感激在这一点上所有的提示和技巧。
编辑:我已经设法避免了这个问题,首先在顶部函数中调用汇编函数emms。这样,fpu将清除与mmx相关的任何垃圾,这些垃圾可能是在调用我的代码的环境中创建的,也可能不是在该环境中创建的。似乎FPU的状态不是理所当然的。
/弗兰克
最佳答案
如果在支持mmx的系统上使用windows queryperformancecounter和queryperformancefrequency函数,请在查询频率/计数器后和计算之前尝试插入femms指令。
__asm femms
我以前遇到过这些函数的问题,它们使用mmx进行64位计算,而没有清除浮点标志/状态。
如果浮点运算之间有任何64位运算,也可能发生这种情况。
关于c - 简单浮点运算的奇怪结果-FPU内部状态不好?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/480562/