Skip to content
Snippets Groups Projects
02-exponentielle5.md 5.68 KiB
Newer Older
Nicolas M. Thiéry's avatar
Nicolas M. Thiéry committed
---
jupytext:
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
kernelspec:
  display_name: C++17
  language: C++17
  name: xcpp17
---

+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "fc78fbcc6c6f5f0b33ef0083fdca373a", "grade": false, "grade_id": "cell-a5a96caf0e3314b2", "locked": true, "schema_version": 3, "solution": false}}

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

+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "c9514403258c211d52d0811f03e530f6", "grade": false, "grade_id": "cell-bc097d26c9102dde", "locked": true, "schema_version": 3, "solution": false}}

## Partie 5 : optimisation ♣

Dans notre cas, il n'est pas très efficace de réutiliser les fonctions
`puissance` et `factorielle` : on refait en effet certains calculs de
nombreuses fois! En effet, tel que nous avons écrit notre fonction
exponentielle, pour calculer $x^{r+1}$ on reprend le calcul du début
(nouvel appel à la fonction puissance) sans utiliser le fait qu'on a
déjà calculé $x^r$ et que $x^{r+1} = x^r \times x$ (et de même pour le
calcul de la factorielle qui est repris du début à chaque appel à la
fonction factorielle alors que $(r+1)! = r! \times (r+1)$). 

Pour éviter ces recalculs, nous allons maintenant définir une nouvelle
version plus efficace de la fonction exponentielle qui ne fait pas
appel aux fonctions puissance ou factorielle.

+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "14330926881dfa9906fb9a0509a6e304", "grade": false, "grade_id": "cell-6d56e4530ad5eb9d", "locked": true, "schema_version": 3, "solution": false}}

:::{admonition} Exercice 1
1.  Copiez-collez ici les fonctions `abs` et `egal` de la
    [partie 3](02-exponentielle3.md) :
:::

```{code-cell}
---
deletable: false
nbgrader:
  cell_type: code
  checksum: ac0b78b2f956da68c7faa5a86096939f
  grade: false
  grade_id: cell-11c71a2c606e0da6
  locked: false
  schema_version: 3
  solution: true
---
// REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE
```

```{code-cell}
---
deletable: false
nbgrader:
  cell_type: code
  checksum: 44ec7a6d5779db1d614df76b5f8ee470
  grade: false
  grade_id: cell-f8b3f1f99b27afb6
  locked: false
  schema_version: 3
  solution: true
---
// REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE
```

:::{admonition} Exercice 1 (suite)
2.  Complétez la fonction ci-dessous qui calcule l'exponentielle à
    précision donnée **sans** utiliser de fonction annexe (sauf
    `egal`), et en procédant de façon plus efficace. Pour cela, vous
    aurez besoin de trois variables d'accumulation : celle de la
    puissance, celle de la factorielle et celle de l'exponentielle.
:::

```{code-cell}
---
deletable: false
nbgrader:
  cell_type: code
  checksum: 907876225de15ea527d95b4db2f0ab72
  grade: false
  grade_id: cell-303a8716a80dcc32
  locked: false
  schema_version: 3
  solution: true
---
/** Calcul rapide de la fonction exponentielle à précision donnée
 * @param x un nombre de type double
 * @param epsilon un nombre de type double
 * @return e^x avec précision epsilon
**/
double expRapide(double x, double epsilon) {
    // REMPLACEZ CETTE LIGNE ET LA SUIVANTE PAR VOTRE RÉPONSE
    throw std::runtime_error("À faire");
}
```

```{code-cell}
---
deletable: false
editable: false
nbgrader:
  cell_type: code
  checksum: 8d0201184bba0f21e1cc937519951ef5
  grade: false
  grade_id: cell-c96d4c17c02ce941
  locked: true
  schema_version: 3
  solution: false
---
expRapide(5, 0.000000001) // 148.413159
```

```{code-cell}
---
deletable: false
editable: false
nbgrader:
  cell_type: code
  checksum: e544e90d711df8993da0ea869a5fbdbb
  grade: false
  grade_id: cell-733b09f1d02a12cf
  locked: true
  schema_version: 3
  solution: false
---
expRapide(3, 0.000000001) // 20.085537
```

```{code-cell}
---
deletable: false
editable: false
nbgrader:
  cell_type: code
  checksum: ee6fce39ac451bf744049ea8b586429b
  grade: false
  grade_id: cell-54872c873b619fe1
  locked: true
  schema_version: 3
  solution: false
---
expRapide(1, 0.000000001) // 2.718282
```

+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "d5946bf20f94f5987f3c8899ada6e0f1", "grade": false, "grade_id": "cell-765bea92acc94ff3", "locked": true, "schema_version": 3, "solution": false}}

:::{admonition} Exercice 1 (suite)
3.  Évaluez la performance de la fonction `expRapide` en utilisant à
    nouveau `timeit`. Est-ce vraiment plus rapide?
:::

```{code-cell}
%timeit expRapide(10, 0.00000001);
```

+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "1a57be5a1f128cccfa27b6c566981aa1", "grade": false, "grade_id": "cell-54073acf05987882", "locked": true, "schema_version": 3, "solution": false}}

## Bilan

Vous avez maintenant une implantation nettement plus rapide de la
fonction exponentielle. Faut-il pour autant toujours tout réimplanter
plutôt que de réutiliser ? Non, surtout pas :

> «Early optimisation is the root of all evil»
>
> -- Donald Knuth

Ici, on pourrait par exemple obtenir les mêmes performances sans
duplication de code par *mémoïsation* (conserver les valeurs déjà
calculées de $n!$ et $x^n$ pour éviter de les recalculer). En général,
c'est à traiter au cas par cas, en tenant compte du compromis entre
temps de dévelopement et performances requises, des questions de
complexité (cf cours à venir), etc.

+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "f3313388c3a778384dc9d70cd75033d4", "grade": false, "grade_id": "cell-c367cfa1df22e874", "locked": true, "schema_version": 3, "solution": false}}

Vous pouvez maintenant passer à la [suite du TP](index.md).