浮点比较`a!= 0.7`

可能重复:
浮点比较中的问题

#include  #include  main() { float a = 0.7; if(a < 0.7) printf("C"); else printf("C++"); } 

在上面的代码中,输出是C 我在Code :: Blocks和Pelles C中尝试了这段代码,但得到了相同的答案。 我想详细了解这个的原因!

在二进制中,0.7是:

 b0.1011001100110011001100110011001100110011001100110011001100110... 

但是, 0.7是双精度文字,其值为0.7舍入到最接近的可表示的双精度值,即:

 b0.10110011001100110011001100110011001100110011001100110 

十进制,这正是:

  0.6999999999999999555910790149937383830547332763671875 

当你写float a = 0.7 ,该double值再次舍入为单精度, a得到二进制值:

 b0.101100110011001100110011 

这正是

  0.699999988079071044921875 

十进制。

当您进行比较(a < 0.7) ,您将此单精度值(转换为double,因为所有单精度值都可以双精度表示)与原始双精度值进行比较。 因为

  0.699999988079071044921875 < 0.6999999999999999555910790149937383830547332763671875 

比较正确返回true,程序打印"C"

请注意,这在C ++中没有任何不同,相反的代码的出现。 某些(数字上不安全的)编译器优化可以改变行为,但这些优化并不是C或C ++独有的。

这是因为0.7具有double类型,因此a被转换为double并且在此类型中进行比较。 由于0.7在二进制浮点中无法准确表示,因此会出现一些舍入误差,并且比较成立。

您可以:

 if( a < 0.7f ) { .... 

但实际上这种效果对C ++也是如此,所以你的条件并不完全正确。

巴特在评论中给出了很好的参考,但我也建议这个非常简单的规则:

并非所有数字都可以在计算机中准确表示,因此只要使用浮点数(例如float和double),就应该期望每个存储的数字中都存在一个小的,不可预测的错误。 不,它不是真正的随机或不可预测,但在你了解更多信息之前,你可以认为它是不可预测的。 因此,诸如a <0.7之类的比较结果可能是真实的,也可能不是。 不要编写依赖于它的代码。