C程序输出不同数字的不同值?

时间:2016-07-09 04:54:53

标签: c++ c comparison type-conversion

参见下面的程序

#include<stdio.h>
int main()
{
    float x = 0.1;
    if (x == 0.1)
        printf("IF");
    else if (x == 0.1f)
        printf("ELSE IF");
    else
        printf("ELSE");
}

这里有另一个程序

#include<stdio.h>

    int main()
    {
        float x = 0.5;
        if (x == 0.5)
            printf("IF");
        else if (x == 0.5f)
            printf("ELSE IF");
        else
            printf("ELSE");
    }

从这两个程序中我们都期望得到类似的结果,因为两者都没有改变,一切都是相同的,而且比较术语也相应地改变了。

但以上2个程序会产生不同的结果

第一个计划

ELSE

第二个计划

IF

为什么这2个程序表现不同

2 个答案:

答案 0 :(得分:1)

这两个程序的行为因计算机和操作系统而异 - 您正在测试floats完全相等

在内存中,floats存储为binary中的一串位 - 即二进制0.1(0.1b)表示十进制0.5(0.5d)。

类似地,

Binary | Decimal
0.1    |  2^-1        = 1/2
0.01   |  2^-2        = 1/4
0.001  |  2^-3        = 1/8
0.11   |  2^-1 + 2^-2 = 3/4

问题是某些小数字没有漂亮的浮点表示。     0.1d = 0.0001100110011001100110011 ... 这是无限长的。

所以,0.5在二进制文件中非常好用

0.5d = 0.1000000000000000...b

但0.1非常讨厌

0.1d = 0.00011001100110011...

现在,根据您的编译器,它可能假设0.1f是double类型,它存储了0.0001100110011001100110011001100110011的无限序列... 因此它不等于float版本,它会更早地截断序列。

另一方面,无论存储多少个小数位,0.5f都是相同的,因为它在第一个位置之后全部为零。

在C ++或C中比较floatdouble s的可接受方式是#define一个非常小的数字(我喜欢称之为EPS,EPSILON的缩写)并替换

float a = 0.1f
if (a == 0.1f) {
    printf("IF\n")
} else {
    printf("ELSE\n")
}

#include <math.h>

#define EPS 0.0000001f

float a = 0.1f
if (abs(a - 0.1f) < EPS) {
    printf("IF\n")
} else {
    printf("ELSE\n")
}

实际上,这可以测试a是否足够接近0.1f而不是精确相等。对于99%的应用程序,这种方法运行得很好,但对于超敏感计算,需要一些涉及使用long double或定义自定义数据类型的陌生技巧。

答案 1 :(得分:0)

您使用的是两种数据类型:double,自动在if(x=0.1)
(0.1为double),x为float。这些类型与存储价值的方式不同。 0.1不是0.1f,是0.100000000001(双)或0.09388383(某物)