C: j’ai obtenu des résultats différents avec pow (10,2) et pow (10, j), j = 2;

celui-ci affiche 100:

int j=2; int i= pow(10,2); printf("%d\n", i); 

et celui-ci imprime 99:

 int j=2; int i= pow(10,j); printf("%d\n", i); 

Pourquoi?

Ce qui se passe, c’est que vous avez une implémentation C dont la bibliothèque standard a une implémentation de pow de très basse qualité qui renvoie des résultats inexacts même lorsque le résultat exact est représentable dans le type ( double ). L’appel à pow(10,2) semble produire la valeur juste en dessous de 100.0 , ce qui, lorsqu’il est arrondi à un entier, donne 99. La raison pour laquelle vous ne voyez pas cela lorsque les arguments sont constants est que le compilateur s’est libéré optimisez l’appel et remplacez-le par une constante 100 au moment de la compilation.

Si votre intention est de faire des pouvoirs entiers, n’utilisez pas la fonction pow . Ecrivez une fonction de puissance entière appropriée ou, lorsque l’exposant est connu, écrivez simplement la multiplication directement.

Dans le premier cas, je suppose que le compilateur a optimisé la valeur à 10*10 sans appeler réellement pow (les compilateurs le font réellement). Dans le second cas, il semble que vous ayez une erreur d’arrondi en virgule flottante. Le résultat est presque 100 mais pas tout à fait, et la conversion implicite vers int tronque.

La fonction pow fonctionne en double , pas en int .

En général (mais pas toujours), lorsque vous convertissez des doubles en entiers, vous appelez round() . Par exemple:

 int i = (int) round(pow(10,j)); 

Si votre bibliothèque C ne possède pas cela, vous pouvez émuler:

 #define round(x) floor((x)+0.5) 

pow renvoie le double et donc si le résultat n’est pas exactement 100 mais légèrement inférieur à ce qu’il sera tronqué lors de la conversion en int et vous recevrez le résultat 99 vous voyez. Il serait intéressant de voir à quoi ressemblent les résultats pour une variable double et le format %f .

La raison pour laquelle vous ne le verrez pas lorsque vous utiliserez des littéraux est due au repliement constant qui optimisera l’appel et le remplacera par une constante. Nous pouvons voir la version qui utilise des constantes lorsque nous générons l’assembly, aucun appel à pow n’est effectué, il ne fait que déplacer le résultat final 100 ( voir en direct ):

 movl $100, -4(%rbp) 

alors que la version 2 appelle réellement pow ( voir en direct ):

 call pow