2010-06-03 193 views
1

有人可以解释这种行为吗?GCC编译时分错误

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,因此它似乎是一个编译时错误。

+5

搜索精度/舍入 – 2010-06-03 04:35:56

+0

如果这是精度/舍入误差,那么第二行也不会同时为6012?正如我所说,第一行的程序集中有6012个,所以编译器在编译时计算它。 – kartikmohta 2010-06-03 04:44:14

+1

在这么简单的代码中发现编译器错误是非常非常不可能的。 – Naveen 2010-06-03 04:45:35

回答

9

运行

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

+0

谢谢,我真的没有正确地工作......应该很容易发现这一点。 – kartikmohta 2010-06-03 04:49:54

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,这就是你所看到的。

你没有看到在你的第二个语句相同的原因是因为它是四舍五入显示由printf,而不是截断,因为是当你转换为int会发生什么。 (请参阅@John Kugelman的答案。)