GCC编译时划分错误

问题描述 投票:0回答:3

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

测试.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,所以这似乎是一个编译时错误。

c gcc
3个回答
10
投票

奔跑

#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。


7
投票
打印时,

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

1
投票

听起来像是一个舍入错误。

300.65000/0.05000
的计算(浮点)类似于
6012.99999999
。当转换为 int 时,它会被截断为
6012
。当然,这一切都是在编译器优化中预先计算的,因此最终的二进制文件只包含值
6012
,这就是您所看到的。

您在第二个语句中看不到相同内容的原因是因为它被 rounded 显示为

printf
,而不是 truncated,就像您投射到
int
时所发生的情况一样。 (参见@John Kugelman 的回答。)

© www.soinside.com 2019 - 2024. All rights reserved.