TP : implanter la fonction exponentielle (4/5)#
Partie 4 : calcul de l’exponentielle avec une précision fixée ♣#
Dans la partie 2, vous avez défini une fonction expRang
qui
calcule une approximation de l’exponentielle en tronquant la somme à
un certain rang décidé à l’avance. Cependant le rang nécessaire pour
obtenir une bonne précision dépend du nombre réel \(x\) pour lequel on
veut calculer \(e^x\). On cherche maintenant à calculer une
approximation de l’exponentielle en fixant la précision et non plus
le rang. Pour cela on va écrire une nouvelle fonction d’approximation
de l’exponentielle, dans laquelle le rang auquel on arrête la somme ne
sera pas décidé à l’avance, mais dépendra de l’évolution du calcul
qu’on est en train de faire.
Exercice 1
copiez-collez dans les quatre cellules suivantes vos fonctions
puissance
etfactorielle
de la partie 1 ainsi queabs
etegal
de la partie 3; si vous avez déjà défini la fonctionegal_relatif
, mettez là ici sous le nomegal
:
Exercice 1 (suite)
Définissez une nouvelle fonction d’approximation de l’exponentielle qui somme les termes \(\frac{x^i}{i!}\) jusqu’à ce que le prochain terme à ajouter ne modifie pas la valeur de la somme, selon la précision donnée :
/** Calcul de la fonction exponentielle à precision fixée
* @param x un nombre de type double
* @param epsilon un nombre de type double
* @return e^x avec précision epsilon
**/
double expPrecision(double x, double epsilon) {
/// BEGIN SOLUTION
double e1 = 0;
double e2 = 1;
int i = 1;
while(not egal(e1,e2,epsilon)) {
e1 = e2;
e2 += puissance(x,i) / factorielle(i);
i += 1;
}
return e2;
/// END SOLUTION
}
double epsilon = 0.000000001
epsilon = 1e-9
Exercice 1 (suite)
Le calcul suivant devrait renvoyer \(2.718 281 828 459\) :
expPrecision(1, epsilon)
Note aux enseignants
À ce stade, selon où en est l’étudiant, la fonction expPrecision
utilisera la version relative ou absolue de egal
. Le test suivant
doit donc passer dans les deux cas. C’est le cas car on utilise des
valeurs de exp
pas trop éloignées de 1
.
Exercice 1 (suite)
Il n’y a pas forcément suffisamment de chiffres significatifs affichés pour le vérifier. Faisons à la place un test :
CHECK( abs( expPrecision(1, epsilon) - 2.718281828459 ) < epsilon )
Exercice 1 (suite)
Attention
Si vous n’avez pas encore défini egal_relatif
dans la partie
3, revenez-y et copiez votre fonction en début
de cette feuille sous le nom de egal
avant de passer à la suite.
Notre test d’arrêt ne garantit en fait pas d’obtenir une précision relative de epsilon : même si le terme suivant est plus petit que epsilon, l’accumulation de tous les termes suivants pourrait largement dépasser epsilon, comme dans les exemples suivants :
CHECK( abs(expPrecision(3, epsilon) - 20.085536923 ) < 5*epsilon )
CHECK( abs( expPrecision(5, epsilon) - 148.413159102 ) < 50*epsilon )
Exercice 1 (suite)
Comparez vos résultats avec la fonction
exp
de C++ définie danscmath
:
#include <cmath>
exp(5)
exp(3)
Bilan de la partie 4#
Très bien, vous avez défini la fonction exponentielle à précision fixée. Maintenant étudions sa performance en calculant son temps d’exécution :
%timeit expPrecision(10, 0.00000001);
Dans la partie 5, vous tenterez d’optimiser cette définition.