我正在调试我的项目,但找不到bug。最后我找到了它。看看代码。你认为一切都很好,结果会是“好!”,不是吗?现在用VC编译(我已经尝试过vs2005和vs2008)。
#include <math.h>
#include <stdio.h>
int main () {
for ( double x = 90100.0; x<90120.0; x+=1 )
{
if ( cos(x) == cos(x) )
printf ("x==%f OK!\n", x);
else
printf ("x==%f FAIL!\n", x);
}
getchar();
return 0;
}魔术双常数是90112.0。当x< 90112.0时,一切都可以,当x> 90112.0时--不行!您可以将cos更改为sin。
有什么想法吗?不要忘记,sin和cos是周期性的。
发布于 2009-09-01 17:36:05
可能是这样的:http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.18
我知道这很难接受,但是浮点运算并不像大多数人期望的那样工作。更糟糕的是,其中一些差异取决于特定计算机浮点硬件的细节和/或在特定编译器上使用的优化设置。你可能不喜欢这样,但事实就是这样。“得到它”的唯一方法是把你对事物应该如何表现的假设放在一边,接受事物实际表现的样子……
(重点是“经常”这个词;其行为取决于您的硬件、编译器等):浮点计算和比较通常由特殊硬件执行,这些硬件通常包含特殊寄存器,并且这些寄存器的位数通常比double多。这意味着中间浮点计算通常比sizeof(double)有更多的位数,当一个浮点值被写入内存时,它经常被截断,经常丢失一些位的精度...
只需记住这一点:浮点比较是棘手和微妙的,并且充满了危险。注意。浮点的实际工作方式与大多数程序员倾向于认为它应该工作的方式是不同的。如果你打算使用浮点,你需要了解它的实际工作原理...
发布于 2009-09-01 17:49:35
正如其他人所指出的,VS数学库在x87 FPU上进行计算,并生成80位的结果,即使类型是double。
因此:
调用
许多数学库和编译器通过在SSE寄存器中执行64位浮点数(如果可用)进行计算,或者在比较之前强制存储和舍入值,或者通过在实际计算cos( )时存储并重新加载最终结果来保护您。你碰巧使用的编译器/库组合就不那么容易理解了。
发布于 2009-09-01 17:40:36
编译器可能生成了最终将64位双精度值与80位内部浮点寄存器进行比较的代码。测试浮点值的相等性很容易出现这样的错误--您几乎总是更好地进行“模糊”比较,比如(fabs(val1 - val2) < EPSILON)而不是(val1 == val2)。
https://stackoverflow.com/questions/1363665
复制相似问题