有人可以解释这种行为吗?
测试.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,所以这似乎是一个编译时错误。
奔跑
#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。
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
听起来像是一个舍入错误。
300.65000/0.05000
的计算(浮点)类似于 6012.99999999
。当转换为 int 时,它会被截断为 6012
。当然,这一切都是在编译器优化中预先计算的,因此最终的二进制文件只包含值 6012
,这就是您所看到的。
您在第二个语句中看不到相同内容的原因是因为它被 rounded 显示为
printf
,而不是 truncated,就像您投射到 int
时所发生的情况一样。 (参见@John Kugelman 的回答。)