【问题标题】:Why the control goes in “else” part? [duplicate]为什么控制进入“其他”部分? [复制]
【发布时间】:2012-08-11 00:15:18
【问题描述】:

可能重复:
Most effective way for float and double comparison
strange output in comparison of float with float literal

int main() 
{
  float a = 0.8;
  if (a == 0.8)
    printf("x\n");
  else 
    printf("y\n");

  return 0;
}

虽然a等于0.8,但它输出y。

【问题讨论】:

标签: c


【解决方案1】:

您使用的是文字 0.8,但这并不一定意味着它是一个浮点数。尝试使用:

if (a==0.8F)

改为

此外,由于计算机内部使用 base-2,表示数字的小数部分非常容易出错。

【讨论】:

    【解决方案2】:

    这是因为浮点数不能准确地表示小数,所以它不完全是 0.8。并且您将 0.8 舍入为浮点数与 0.8 舍入为小数进行比较,这不一定相同。

    【讨论】:

      【解决方案3】:
      if (a==0.8f)
      

      试试这个。默认情况下,类型被认为是双精度误差比较。

      【讨论】:

        【解决方案4】:

        0.8 无法用二进制浮点数准确表示。您的代码if (a == 0.8) 基本上是比较单精度 0.8 和双精度 0.8,它们不相等。

        要亲自查看,请尝试以下代码:

        int main()
        {
            double a = 0.8f;
            double b = 0.8;
        
            printf("%lX\n", *(long *)&a);
            printf("%lX\n", *(long *)&b);
        }
        

        它输出:

        3FE99999A0000000
        3FE999999999999A
        

        【讨论】:

        • @user1202136:您在哪个平台上运行了该测试?
        • @MichaelBurr:我在英特尔处理器上的 Ubuntu 12.04 / 64 位上运行它。为什么?你没有得到相同的值吗?
        • @user1202136:甚至没有接近 - 正如 H2CO3 所提到的,发布的代码有 UB,并且 amd64 不像在 32 位 x86 上那样简单地在堆栈上传递 varargs(至少对于浮点 args - 我不记得所有的细节),所以你得到的打印数据实际上与你传递的浮点值无关。 0.8 的实际 IEEE 十六进制表示为:3f4ccccd(32 位浮点数)、3fe99999a0000000(32 位浮点数转换为 64 位双精度)和3fe999999999999a(双精度)。
        • @MichaelBurr:你是对的。我修复了上面的代码。非常感谢您的关注。
        【解决方案5】:

        浮点数不是精确值。您不应该使用 == 和 != 来比较它们。使用具有相当小的 epsilon 的大于和小于运算符:

        if ((a > 0.79) && (a < 0.81))
        

        【讨论】:

          【解决方案6】:

          浮点数并不总是 100% 准确,它们不可能是因为它们的存储方式。如果你说float a = 0.8,a 可能真的是0.800000000001 或类似的东西。为了弥补这一点,您应该使用某种阈值。试试if (fabs(a-0.8) &lt; 1.0e-5)

          【讨论】:

            【解决方案7】:

            因为对于浮点数 0.8 并不真正意味着 0.8 但它是 0.799999999 所以它发生了 为什么是 0.79999999
            这取决于浮点值的存储。十进制值将以二进制形式存储 (....,2^3,2^2,2^1,2^0,.,2^-1,2^-2,2^-3,.. .)

            因此,当 0.8 以 2 的倍数存储为 .101b(不是 0.8 而是 0.799999988)时。因此它的值将小于 0.8。

            if (a > 0.8) 
            

            也是False这就是为什么。

            为你的结果尝试

            if (a == 0.8f) 
            

            【讨论】:

              【解决方案8】:

              您正在比较 2 个不同类型的值:a 的类型为 float0.8 的类型为 double

              在比较之前,float 值转换为 double ...但从 double 转换为 float 并返回不一定会产生相同的值

              if (0.8 == (double)(float)0.8) /* ... */
              

              【讨论】:

                猜你喜欢
                • 2012-08-10
                • 2020-09-28
                • 2017-01-31
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-08-30
                • 1970-01-01
                • 2021-07-11
                相关资源
                最近更新 更多