2017-01-13 1 views
1

Je viens d'essayer trois morceaux de code:A propos de la fonction pow en C++

#include<cstdio> 
#include<cmath> 
#include<cstring> 
int main() 
{ 
    int a = 3; 
    int b = pow(10,a); 
    printf("%d",b); 
    return 0; 
} 
//Output:1000 

#include<cstdio> 
#include<cmath> 
#include<cstring> 
int main() 
{ 
    int a = 3; 
    int b = pow(10,a-1); 
    printf("%d",b); 
    return 0; 
} 
//Output:99 

#include<cstdio> 
#include<cmath> 
#include<cstring> 
int main() 
{ 
    int a = 3; 
    int b = pow(10,a-2); 
    printf("%d",b); 
    return 0; 
} 
//Output:10 

Je voudrais savoir pourquoi le deuxième bloc de code sortie 99, est-ce à cause de la précision en virgule flottante? Ou est-ce parce que je devrais employer des nombres de flotteur dans la fonction de pow? (Tels que 10.0) Je suis habituellement confus au sujet de l'exactitude de C++, je vous serai reconnaissant pour votre aide.

+3

Longue histoire courte: 'pow' n'est pas pour maths entières. –

+0

Vous * utilisez * des nombres à virgule flottante avec 'pow', vous ne faites que les convertir d'entiers et inversement. –

+1

Ce n'est pas le '10' vs' 10.0' qui pose problème. Le problème est le 'int b ...' qui signifie que toute imprécision dans le retour de 'pow (10, 2)' sera simplement tronquée. Donc '99.9999999 + un peu d'epsilon' deviendra' 99'. (Bien que je suis un peu surpris que 'pow (10,2)' ne renvoie pas le résultat '100' précisément, cela a probablement quelque chose à voir avec la norme à virgule flottante.) –

Répondre

0

La conversion d'une valeur à virgule flottante en nombre entier se fait par troncature - l'entier suivant est le plus proche de zéro. Si pow est imprécis et trop bas, alors la troncature l'exacerbe.

lround(pow(10,2)) pourrait être plus approprié.

0

Pour entier exposants le modèle suivant peut être très pratique:

template <typename T> inline constexpr T pow(T base, int exponent) 
{ 
    return (exponent == 0) ? static_cast<T>(1.0) : ((exponent>0) ? base*pow(base, exponent-1) : pow(static_cast<T>(1.0)/base, -exponent)); 
} 

Si vous prévoyez de l'utiliser avec un standard C++ avant 11 C++, il suffit de retirer le mot-clé constexpr.

+0

pourriez-vous expliquer un peu ce qu'il fait .. –

+0

En C++ 14 en avant, le corps peut être simplement 'T ret = 1; pour (exponent -) ret * = base; return ret; ' – Potatoswatter

+0

Parlez-vous d'une méthode simple d'exponentiation? À quel point est-ce efficace? –