2010-06-03 195 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的答案。)