2010-06-03 6 views
1

Quelqu'un peut-il expliquer ce comportement?GCC compile erreur de division de temps

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 

J'ai vérifié le code assembleur et il met à la fois les arguments de la première printf comme 6012, il semble y avoir un bug de compilation .

+5

recherche de précision/arrondi –

+0

S'il s'agissait d'une erreur de précision/d'arrondi, la deuxième ligne n'aurait-elle pas les deux comme 6012? Et comme je l'ai dit, il y a 6012 dans l'assembly pour la première ligne, donc le compilateur le calcule pendant la compilation. – kartikmohta

+1

trouver un bug complier dans un tel morceau de code est très très très peu probable. – Naveen

Répondre

9

Run

#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; 
} 

et il devrait être plus clair. La valeur du second (après la division en virgule flottante, qui n'est pas exacte) est ~ 6012.9999999999991, donc quand vous le tronquez avec (int), gcc est assez intelligent pour mettre en 6012 au moment de la compilation.

Lorsque vous imprimez les flottants, printf les formate par défaut pour un affichage avec seulement 6 chiffres de précision, ce qui signifie que la seconde impression est 6013.000000.

+0

Merci, je n'ai pas vraiment travaillé correctement ... aurait dû repérer cela facilement. – kartikmohta

7

printf() arrondit les nombres à virgule flottante lorsque vous les imprimez. Si vous ajoutez plus de précision, vous pouvez voir ce qui se passe:

$ 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

sonne comme une erreur d'arrondi. 300.65000/0.05000 est en cours de calcul (virgule flottante) comme quelque chose comme 6012.99999999. Lors de la diffusion en tant qu'int, il est tronqué à 6012. Bien sûr, tout cela est précalculé dans les optimisations du compilateur, donc le binaire final contient juste la valeur 6012, ce que vous voyez.

La raison pour laquelle vous ne voyez pas la même chose dans votre deuxième déclaration est parce qu'il est d'être arrondi pour l'affichage par printf, et non tronquée, comme ce qui se passe lorsque vous lancez à int. (Voir la réponse de John Kugelman.)