【问题标题】:GCC compile time division errorGCC编译时除错误
【发布时间】:2010-06-03 04:34:46
【问题描述】:

有人可以解释这种行为吗?

test.c:

#include <stdio.h>

int main(void)
{
    printf("%d, %d\n", (int) (300.6000/0.05000), (int) (300.65000/0.05000));
    printf("%f, %f\n", (300.6000/0.05000), (300.65000/0.05000));
    return 0;
}

$ gcc test.c

$ ./a.out
6012, 6012
6012.000000, 6013.000000

我检查了汇编代码,它把第一个 printf 的两个参数都设置为 6012,所以这似乎是一个编译时错误。

【问题讨论】:

  • 搜索精度/舍入
  • 如果是精度/舍入误差,第二行不是也都为 6012 吗?正如我所说,第一行的程序集中有 6012,所以编译器在编译时计算它。
  • 在如此简单的代码中找到编译器错误是非常非常不可能的。
  • 足够高 (> 6012.999999) printf 打印 6013.000000,但仍介于 6012 和 6013 之间,因此截断为 6012。

标签: c gcc compiler-construction


【解决方案1】:

运行

#include <stdio.h>

int main(void)
{
    printf("%d, %d\n", (int) (300.6000/0.05000), (int) (300.65000/0.05000));
    printf("%.20f %.20f\n", (300.6000/0.05000), (300.65000/0.05000));
    return 0;
}

而且应该更清楚。第二个的值(浮点除法后,不准确)约为 6012.9999999999991,所以当你用 (int) 截断它时,gcc 足够聪明,可以在编译时输入 6012。

当您打印浮点数时,默认情况下 printf 会将它们格式化为仅以 6 位精度显示,这意味着第二个打印为 6013.000000。

【讨论】:

  • 谢谢,我真的没有正确解决它......应该很容易发现这一点。
【解决方案2】:

printf() 在打印浮点数时对其进行舍入。如果您添加更多精度,您可以看到正在发生的事情:

$ cat gccfloat.c
#include <stdio.h>

int main(void)
{
    printf("%d, %d\n", (int) (300.6000/0.05000), (int) (300.65000/0.05000));
    printf("%.15f, %.15f\n", (300.6000/0.05000), (300.65000/0.05000));
    return 0;
}

$ ./gccfloat
6012, 6012
6012.000000000000000, 6012.999999999999091

【讨论】:

    【解决方案3】:

    听起来像是舍入错误。 300.65000/0.05000 正在计算(浮点)为类似于 6012.99999999 的东西。当转换为 int 时,它会被截断为 6012。当然,这一切都是在编译器优化中预先计算出来的,所以最终的二进制文件只包含值6012,这就是你所看到的。

    您在第二个语句中没有看到相同的原因是因为它被 四舍五入 以供 printf 显示,而不是 截断,就像发生的那样当您投射到int 时。 (见@John Kugelman 的回答。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-28
      • 2017-06-27
      • 1970-01-01
      相关资源
      最近更新 更多