【问题标题】:gcc is not comparing double type variables correctly?gcc 没有正确比较双精度类型变量?
【发布时间】:2012-12-29 07:27:28
【问题描述】:

我什至不确定我是在问一个问题,这次我找到了一种“迂回”的方式,但是……我花了几天时间才意识到这是问题所在,而且……好吧,换个时间我可能无法绕过它......还有其他人来过这个吗?比较实际上相等的双精度类型变量时,结果是 ">"...

 printf("compare: %ld ?? %ld\n", (double)( radii(nowX,nowY)*irange2 ),(double)(Rad2*irange2)); getchar();
 if( (double)(radii(nowX,nowY)*irange2)<(double)(Rad2*irange2) ) printf("*** < ***\n"); 
 if( (double)(radii(nowX,nowY)*irange2)>(double)(Rad2*irange2) ) printf("*** > ***\n");
 if( (double)(radii(nowX,nowY)*irange2)==(double)(Rad2*irange2) ) printf("*** == ***\n")
 printf("SECOND = %d\n", ((double)(radii(nowX,nowY)*irange2))<= ( (double)(Rad2*irange2)

输出:

compare: 1509949.440000 ?? 1509949.440000
*** > ***
SECOND = 0

 printf("compare: %ld ?? %ld\n", (long)( radii(nowX,nowY)*irange2 ), (long)(Rad2*irange2)); getchar();
 if( (long)(radii(nowX,nowY)*irange2)<(long)(Rad2*irange2) ) printf("*** < ***\n");
 if( (long)(radii(nowX,nowY)*irange2)>(long)(Rad2*irange2) ) printf("*** > ***\n"); 
 if( (long)(radii(nowX,nowY)*irange2)==(long)(Rad2*irange2) ) printf("*** == ***\n")
 printf("SECOND = %d\n",  ((long)(radii(nowX,nowY)*irange2))<= ( (long)(Rad2*irange2) ) ); getchar();

输出:

compare: 1509949 ?? 1509949

*** == ***
SECOND = 1

【问题讨论】:

  • 这是一个众所周知的浮点运算问题。在 SO 或您选择的任何其他搜索引擎上搜索“每个计算机科学家应该了解的关于浮点运算的知识”。你会发现所有你需要知道的。困难的部分将是为此找到最好的重复问题。

标签: gcc floating-point double


【解决方案1】:

这里的问题是浮点算术是用来做近似算术的,所以它得到的结果有各种错误,而且你没有显示数字的完整值。

当完全显示时,数字看起来不相等。

比较相等不是这里的有罪操作。当输入不正确时,几乎所有函数都无法给出正确的结果。例如,如果您计算一个值的平方根,如果计算准确,则该值将为零或正,但由于先前的舍入误差而略微为负,那么您将获得一个取负数平方根的异常。

在舍入近似结果、减去近似结果(以增加相对误差的幅度而臭名昭著)和其他函数时,也会出现类似的问题。 所有浮点运算,而不仅仅是比较相等性,应考虑到结果是近似的事实(除非经过精心设计)。

【讨论】:

    【解决方案2】:

    发生这种情况是因为,根据计算,双精度值可能会略有不同。因此不建议检查是否相等。相反,请检查两个双打是否非常彼此靠近。另请参阅 this link 了解说明。

    编辑:只是为了澄清这一点:这适用于所有浮点类型,因为这是它们存储方式所固有的。

    【讨论】:

    • 谢谢大家,非常感谢!我以前没有这个问题 - 而且,嗯,我曾经使用过'=='......有时......与浮动/双打 - 不是很多,我想,我想我只是幸运,但谢谢你这么多 - 现在我知道这不仅仅是这台特定机器上的一些奇怪行为(正如我最初怀疑的那样),并且不会冒陷入大混乱的风险!再次感谢您!
    • @KatiAvramova,请单击左侧的复选标记接受此答案。这会将这个问题标记为已解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-09
    • 2015-12-17
    相关资源
    最近更新 更多