【问题标题】:I cant understand this program [duplicate]我无法理解这个程序[重复]
【发布时间】:2012-08-01 12:11:28
【问题描述】:

可能重复:
strange output in comparision of float with float literal

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

#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;
}

如何解决这个问题?

【问题讨论】:

  • a 中的 0.8 比 if 语句中的 0.8 精度低,因此提升中的错误会导致意外结果。
  • 我在某处读到浮点数的默认数据类型是双精度
  • float只有32位,float a中的0.8用32位表示,而if语句中的0.8则是double64位.
  • 你确定这编译正确吗?因为 if 条件中 > 运算符的左侧是常数?即使它编译a
  • @rain 它可以正确编译两种方式

标签: c if-statement floating-point operators


【解决方案1】:

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

其他人似乎认为您在询问一些浮点舍入问题。但是,即使使用精确的数学,.8 &gt; .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 &gt; a 为假。

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

【讨论】:

    【解决方案2】:

    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 现在有一些非常小的派系部分

    【讨论】:

    • 在我的书中写到 0.8>a 因为 0.8 是双精度,而 a 是浮点数..但输出是其他的
    • 您将数字的值与其大小混为一谈。双精度数是位数的两倍,但值将接近或相同,具体取决于浮点数本身。
    • PS:Eric,我是在 Mac 上运行的 :-)
    • 从 float 到 double 的提升不会改变值。从 double 到 float 的转换确实如此。
    猜你喜欢
    • 2014-01-21
    • 1970-01-01
    • 2014-04-01
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    • 2020-10-04
    相关资源
    最近更新 更多