浮点比较`a!= 0.7`

时间:2011-07-30 13:12:35

标签: c comparison floating-point

  

可能重复:
  problems in floating point comparison

#include <stdio.h>
#include <conio.h>

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

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

3 个答案:

答案 0 :(得分:20)

在二进制中,0.7是:

b0.1011001100110011001100110011001100110011001100110011001100110...

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

b0.10110011001100110011001100110011001100110011001100110

十进制,这正是:

 0.6999999999999999555910790149937383830547332763671875

当您编写float a = 0.7时,该双精度值再次舍入为单精度,a获取二进制值:

b0.101100110011001100110011

这正是

 0.699999988079071044921875

十进制。

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

 0.699999988079071044921875 < 0.6999999999999999555910790149937383830547332763671875

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

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

答案 1 :(得分:8)

这是因为0.7的类型为double,因此a会转换为double并在此类型中进行比较。由于0.7在二进制浮点中无法完全表示,因此会出现一些舍入误差,并且比较结果为真。

你可以:

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

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

答案 2 :(得分:3)

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

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