浮点比较

时间:2011-08-10 13:01:44

标签: c++ c floating-point

int main()
{
    float a = 0.7;
    float b = 0.5;
    if (a < 0.7)
    {
       if (b < 0.5) printf("2 are right");
       else         printf("1 is right");
    }
    else printf("0 are right");
}

我希望此代码的输出为0 are right。 但令我沮丧的是,输出是1 is right为什么?

5 个答案:

答案 0 :(得分:130)

int main()
{
    float a = 0.7, b = 0.5; // These are FLOATS
    if(a < .7)              // This is a DOUBLE
    {
      if(b < .5)            // This is a DOUBLE
        printf("2 are right");
      else
        printf("1 is right");
    }
    else
      printf("0 are right");
}

浮点数在比较期间被提升为双打,因为浮点数不如双精度浮点数0.7,因为浮点数与0.7相同,为double。在这种情况下,0.7当浮动变得低于0.7时,它被提升为双倍。正如Christian所说,0.5是2的幂总是完全表示,所以测试按预期工作:0.5 < 0.5是假的。

所以:

  • float更改为double或:
  • .7.5更改为.7f.5f

你会得到预期的行为。

答案 1 :(得分:15)

问题是您要比较的常量是double而不是float。此外,将常量更改为易于表示的内容(例如5因子)会使其显示0 is right。例如,

main()
{
    float a=0.25,b=0.5; 
    if(a<.25) 
       {
       if(b<.5) 
               printf("2 are right");
       else
               printf("1 is right");
       }
else
printf("0 are right");
}

输出:

0 are right

Most Effective Way for float and double comparison 上的这个问题涵盖了这个主题。

另外,这篇关于floating point number comparison的天鹅座的文章给了我们一些提示:

  

IEEE浮点数和双精度格式的设计是为了数字   是“按字典顺序排列的”,用IEEE的话说   建筑师威廉卡汉的意思是“如果两个浮点数   相同的格式是有序的(比如x&lt; y),然后它们的排序相同   当它们的位被重新解释为Sign-Magnitude整数时。“

     

这意味着如果我们在内存中使用两个浮点数,则解释它们的位   模式作为整数,并比较它们,我们可以分辨哪个更大,   没有做浮点比较。在C / C ++语言中   比较看起来像这样:

if (*(int*)&f1 < *(int*)&f2)
  

这种迷人的语法意味着取f1的地址,将其视为一个   整数指针,并取消引用它。所有这些指针操作看起来   昂贵,但他们基本上都取消了,只是意味着'治疗f1   作为整数'。因为我们将相同的语法应用于f2整行   表示'比较f1和f2,使用它们的内存表示   解释为整数而不是浮点数。

答案 2 :(得分:3)

这是由于从float转换为double时的舍入问题

答案 3 :(得分:2)

通常比较与浮点数的相等性是一项危险的业务(当你在&gt;的边界上进行比较时,这实际上是你所做的事情),请记住,在十进制中某些分数(如1/3)无法表达确切地说,二进制也是如此,

0.5= 0.1,在float或double中都是相同的。

0.7=0.10110011001100等永远,0.7不能用二进制精确表示,你得到舍入错误,并且浮点数和双精度之间可能(非常非常轻微)不同

请注意,在浮点数和双精度数之间切换不同的小数位数,因此结果不一致。

答案 4 :(得分:0)

另外,顺便说一句,你的0逻辑错误是正确的。输出0时,不检查b是否正确。但是你真正想要完成的事情有点神秘。浮点数和双精度数之间的浮点比较将具有变化,分钟,因此您应该与您的情况的delta'可接受'变化进行比较。我总是通过仅执行工作的内联函数完成此操作(使用宏执行一次,但这太麻烦了)。无论如何,是的,圆形问题比比皆是这类例子。读取浮点数,并知道.7与.7f不同,并将.7赋给float会将double转换为float,从而改变值的确切性质。但是,关于b错误的编程假设,因为你检查了一下,我不得不注意到:)