浮动比较给出了不同的结果

时间:2011-09-28 08:28:08

标签: c++ c floating-point

请看以下两个代码,并告诉我答案变化很大的原因。

#include<stdio.h>
int main() {
    float a = 0.9;
    if(a<0.9)
        printf("hi"); // This will be the answer
    else
        printf("bye");
    return 0;
}

如果我们将0.9更改为0.8,则会打印其他语句:

#include<stdio.h>
int main() {
    float a = 0.8;
    if(a<0.8)
        printf("hi");
    else
        printf("bye");//this will be the answer
    return 0;
}

那么,当我们改变一个数字时,为什么这个输出会改变?

7 个答案:

答案 0 :(得分:10)

此错误是由浮点精度引起的,因为您要将float类型与double值进行比较。尝试将其与浮点文字进行比较:if(a<0.8f)

我建议您阅读相应的wikipedia article,它会详细解释您的错误发生的原因。

答案 1 :(得分:5)

文字0.90.8的类型为double。由于两个值都无法准确表示,因此它们实际上是0.9000000000000000222...0.8000000000000000444...

当存储在float(单精度)变量a中时,它们将转换为单个变得更加不准确:0.89999997...0.8000000119...

为了与文字double值进行比较,它们会转换回double,保留更准确的值。

从上面的数字可以看出,比较会为0.90.8产生不同的结果。

所有这一切都假设您的平台具有IEEE754浮动,这很可能就是这种情况。

您可以在www.binaryconvert.com看到数字的单/双表示。

答案 2 :(得分:1)

您必须知道浮点的工作原理。

浮点数用2的幂表示,每个数字用于表示2^-x,其中X是第n个数字。

例如,0.011(二进制)为2^-2 + 2^-3,即0.25 + 0.125 = 0.375

现在尝试代表0.9。你有麻烦,因为没有两个人的力量代表它。在32位且可能是64位机器中表示的值将给出略小于0.9的结果,而对于0.8,结果是精确的并且可以用两个的幂表示。

您可以通过打开python提示进行尝试。尝试输入一些数字,最后会以...99999999结尾。

答案 3 :(得分:1)

根据C标准:

  

6.3.1.5真正的浮动类型

     

1)当float被提升为double或long double时,或者是double   提升为长双,其价值不变。

     

2)当双人被降级为浮动时,长双人被降级为双人   浮动,或以更高的精度和范围表示的值   它的语义类型(见6.3.1.8)所要求的是明确的   转换为语义类型,如果转换的值可以   完全代表新类型,它没有变化。如果值   被转换的范围是可以表示的值,但是   无法准确表示,结果要么是最接近的   或最接近的较低可表示值,选择在   实现定义的方式。如果转换的值在外面   可以表示的值范围,行为未定义。

标准可以在 here 找到。

答案 4 :(得分:0)

首先,正如其他人所提到的,在使用0.8f时使用float之类的值。

此外,由于FPU中此操作的精确性,您需要避免浮点==比较。对我来说最有效的方法是定义一个保证金,假设1e-6f(或根据你的应用需要的精度),而不是:

if (LHS == RHS)
你写道:

if (LHS-RHS < MARGIN && RHS-LHS < MARGIN)

你可以编写一个函数(如果你是一个c ++粉丝)或宏(如果你是一个粉丝(这里是-1s)),它会为你做这个。

答案 5 :(得分:0)

这是由于舍入错误,要查看您在if之前使用插入printf的值:

printf("a=%f\n", a);

答案 6 :(得分:-1)

试试这个:

使用“if(a&lt; 0.9f)”而不是“if(a <0.9)”进行比较