【问题标题】:C program outputting different values with different numbers? [duplicate]C程序输出不同数字的不同值? [复制]
【发布时间】:2016-11-11 17:18:27
【问题描述】:

请看下面的程序

#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

为什么这两个程序的行为不同

【问题讨论】:

标签: c++ c comparison type-conversion


【解决方案1】:

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

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

同样,

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 中比较 floats 或 doubles 的公认方法是 #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,或定义自定义数据类型。

【讨论】:

    【解决方案2】:

    您正在使用两种数据类型:双精度,自动在
    if(x=0.1))
    (0.1 是双精度)和 x 是浮点数。这些类型存储值的方式不同。 0.1 不是 0.1f,它是 0.100000000001 (double) 或 0.09388383(something)

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-16
    • 1970-01-01
    • 2012-07-23
    • 2020-06-16
    相关资源
    最近更新 更多