-1

可能重复:
与浮点文字比较的奇怪输出

我无法理解这段代码。如何比较两个相同的数字?

#include<stdio.h>

int main()
{
    float a=0.8;
    if(0.8>a)     //how can we compare same numbers?
        printf("c");
    else
        printf("c++");
    return 0;
}

如何解决这个问题?

4

2 回答 2

2

我不明白你为什么问是否可以比较相同的两个数字。3 > 3即使 3 与 3 相同,您为什么不期望这样的比较起作用?如果>左侧大于右侧,则运算符返回 true,否则返回 false。在这种情况下,.8不大于a,因此结果为假。

其他人似乎认为您在询问一些浮点舍入问题。但是,即使使用精确的数学,.8 > .8也是错误的,这就是您使用显示的代码得到的结果;else 分支被占用。所以这里没有意外的行为可以解释。

你真正的问题是什么?

如果您询问浮点效果,以下是一些信息。

在 C 源代码中,文本“.8”代表可以用双精度表示的最接近 0.8 的数字之一。(一个好的实现使用最接近的数字,但 C 标准允许一些松弛。)在最常见的浮点格式中,最接近 0.8 的双精度值是(作为十六进制浮点数字)0x1.999999999999ap- 1,即(十进制)0.8000000000000000444089209850062616169452667236328125。

这样做的原因是二进制浮点仅用代表2 的幂的位来表示数字。(2 的哪个幂取决于浮点值的指数,但无论指数如何,小数部分中的每一位都表示 2 的某个幂,例如 0.5、0.25、0.125、0.0625 和依此类推。)由于 .8 不是任何 2 的幂的精确倍数,因此,当小数部分中的可用位全部使用时,结果值仅接近 0.8;这不准确。

初始化float a = .8;将双精度值转换为单精度值,以便可以将其分配给 a。在单精度中,最接近 0.8 的可表示数字是 0x1.99999ap-1(十进制,0.800000011920928955078125)。

因此,当您将“.8”与 a 进行比较时,您会发现这.8 > a是错误的。

对于其他一些值,例如 0.7,最接近的可表示数字的计算方式不同,并且关系运算符返回 true。例如,.7 > .7f是真的。(源代码中的文本“.7f”代表接近 0.7 的单精度浮点值。)

于 2012-08-01T12:48:25.010 回答
1

0.8 是双倍。当 a 设置为它时,它会转换为浮点数,此时会失去精度。比较采用浮点数并将其提升回双精度,因此值肯定不同。

编辑:我可以证明我的观点。我只是编译并运行了一个程序

float a = 0.8;
int b = a == 0.8 ? 1 : 0;
int c = a < 0.8 ? 1 : 0;
int d = a > 0.8 ? 1 : 0;

printf("b=%d, c=%d, d=%d, a=%.12f 0.8=%.12f \n", b, c, d, a, 0.8);
b=0, c=0, d=1, a=0.800000011921 0.8=0.800000000000

请注意,由于晋升为双倍,现在 a 现在有一些非常小的派系部分

于 2012-08-01T12:14:40.400 回答