TP : implanter la fonction exponentielle (4/5)#

Partie 4 : calcul de l’exponentielle avec une précision relative fixée ♣#

Dans la partie 2, vous avez implanté 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.

Commencez par copier-coller dans les quatre cellules suivantes vos fonctions puissance et factorielle de la partie 1 ainsi que abs et egal de la partie 3:

// REMPLACER CETTE LIGNE PAR VOTRE RÉPONSE
// REMPLACER CETTE LIGNE PAR VOTRE RÉPONSE
// REMPLACER CETTE LIGNE PAR VOTRE RÉPONSE
// REMPLACER CETTE LIGNE PAR VOTRE RÉPONSE

Implantez 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) {
    // REMPLACER CETTE LIGNE ET LA SUIVANTE PAR VOTRE RÉPONSE
    throw std::runtime_error("À faire");
}
double epsilon = 0.000000001
epsilon = 1e-9

Le calcul suivant devrait renvoyer \(2.718 281 828 459\) :

expPrecision(1, epsilon)

Il n’y a pas forcément suffisament de chiffres significatifs affichés pour le vérifier. Faisons à la place un test :

CHECK( abs( expPrecision(1, epsilon) - 2.718281828459 ) < epsilon )

Notre test d’arrêt ne garantit en fait pas d’obtenir une précision 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 )

Comparez vos résultats avec la fonction exp de C++ définie dans cmath :

#include <cmath>
exp(5)
exp(3)

Bilan de la partie 4#

Très bien, vous avez implanté le calcul de 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 implantation.