2011-07-30 112 views
4

可能重复:!
problems in floating point comparison浮点比较`一个= 0.7`

#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中试过这段代码,但得到了相同的答案。我想知道详细的原因!

+6

看看[浮点指南](http://floating-point-gui.de/)和[每个计算机科学家应该知道的有关浮点运算的知识](http://download.oracle。 com/docs/cd/E19957-01/806-3568/ncg_goldberg.html) – Bart

回答

19

在二进制,0.7是:

b0.1011001100110011001100110011001100110011001100110011001100110... 

然而,0.7是一个双精度文字,其值0.7舍入到最接近的表示的双精度值,这是:

b0.10110011001100110011001100110011001100110011001100110 

十进制,就是这样:

0.6999999999999999555910790149937383830547332763671875 

当你写,即双值再次舍入到单精度和a得到二进制值:

b0.101100110011001100110011 

这正是

0.699999988079071044921875 

十进制。

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

0.699999988079071044921875 < 0.6999999999999999555910790149937383830547332763671875 

比较正确返回true,并且您的程序打印"C"

请注意,这与C++没有任何区别,相反的代码出现。有一些(数字上不安全的)编译器优化可以改变行为,但这些不是C或C++特有的。

+0

好的demontstration,+1 – unkulunkulu

+0

好的...非常感谢你!它帮助了很多! –

8

这是因为0.7的类型为double,所以a转换为double并在此类型中进行比较。由于0.7在二进制浮点中不能完全表示,因此会出现舍入错误并且比较成立。

您可以:

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

但实际上这种影响是真实的C++,这样你的条件是不完全合法的。

+0

好的。 –

3

巴特给了在他的评论很好的参考,但我也建议这个非常简单的规则:当您使用浮点数

并非所有的数字可以精确地用计算机来表示,所以一旦(例如作为浮点数和双精度数),您应该期望在每个存储的数字中可能存在一个小的,不可预知的错误。不,它不是真正的随机或不可预测的,但是直到你对它有更多的了解,你才会认为它是不可预测的。因此,比较例如a < 0.7可能是事实,它可能不是。不要编写依赖它的代码。

+0

我从来没有使用这种比较,但如果我必须比较一些浮点值呢? –