Chapitre 1016 minIntermédiaire
Méthodes numériques en Python : dichotomie, Newton, trapèzes
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- encadrer une solution de f(x) = 0 par balayage et par dichotomie ;
- prévoir le nombre d'étapes d'une dichotomie avec log₂ ;
- appliquer la méthode de Newton ;
- approcher une intégrale par le point milieu, les trapèzes et Monte-Carlo.
5 exercices corrigés2 schémas
Quand une équation f(x) = 0 ou une intégrale ne se calcule pas à la main, on en cherche une valeur approchée par un algorithme : balayage, dichotomie ou méthode de Newton pour l'équation ; point milieu, trapèzes ou Monte-Carlo pour l'intégrale. Le programme du BTS cite ces méthodes et demande d'en programmer au moins une. Ce chapitre les code en Python, sur deux exemples qu'aucune formule ne résout, et compare leur précision.
Deux problèmes sans solution exacte
Une équation. Résoudre eˣ + x − 3 = 0. Aucune manipulation avec ln ne sort x de l'exponentielle et du terme x à la fois. Mais on sait qu'il y a une solution unique : f(x) = eˣ + x − 3 a pour dérivée eˣ + 1 > 0, elle est strictement croissante, et f(0) = −2 < 0 < f(1) = e − 2 ≈ 0,718. Il y a donc une seule solution α, entre 0 et 1 (chapitre 3).
Une intégrale. Calculer ∫₀¹ e^(−x²) dx. La fonction e^(−x²) est continue et positive, l'aire sous sa courbe existe, mais elle n'a aucune primitive qui s'écrive avec les fonctions usuelles. À un changement d'échelle près, c'est la courbe en cloche de la loi normale : c'est pour cela que la calculatrice, et non une formule, calcule les probabilités de la loi normale.
Le balayage
On avance de x = a à x = b par pas réguliers, et on s'arrête au premier intervalle où f change de signe, c'est-à-dire où f(x) × f(x + pas) ≤ 0.
from math import exp
def f(x):
return exp(x) + x - 3
def balayage(f, a, b, pas):
"""Premier intervalle [x ; x + pas] de [a ; b] sur lequel f change de signe."""
n = round((b - a) / pas) # nombre de tranches
for i in range(n):
x = round(a + i * pas, 10) # arrondi : 0.1 n'est pas exact en binaire
if f(x) * f(x + pas) <= 0:
return x, round(x + pas, 10)
return None
print(balayage(f, 0, 1, 0.1))
print(balayage(f, 0.7, 0.8, 0.01))
(0.7, 0.8)
(0.79, 0.8)
Premier passage au pas de 0,1 : α est entre 0,7 et 0,8. Deuxième passage au pas de 0,01 : α est entre 0,79 et 0,80. Chaque chiffre de plus coûte un nouveau balayage d'une dizaine de calculs.
La dichotomie
La dichotomie coupe l'intervalle en deux à chaque étape, comme la recherche dichotomique dans un tableau trié (chapitre 6) : on calcule f au milieu m, et on garde la moitié où f change de signe.
from math import exp
def f(x):
return exp(x) + x - 3
def dichotomie(f, a, b, precision):
"""Encadrement [a ; b] d'amplitude au plus precision d'une solution de f(x) = 0.
Précondition : f est continue sur [a ; b] et f(a), f(b) sont de signes contraires."""
etapes = 0
while b - a > precision:
m = (a + b) / 2
if f(a) * f(m) <= 0: # le changement de signe est dans [a ; m]
b = m
else: # sinon, il est dans [m ; b]
a = m
etapes = etapes + 1
return a, b, etapes
print(dichotomie(f, 0, 1, 0.001))
print(dichotomie(f, 0, 1, 1e-6))
(0.7919921875, 0.79296875, 10)
(0.7920598983764648, 0.7920608520507812, 20)
Avec 10 étapes, α est connu à 10⁻³ près ; avec 20 étapes, à 10⁻⁶ près : α ≈ 0,792 06.
La dichotomie est lente mais sûre : tant que f est continue et change de signe sur l'intervalle de départ, elle converge, et l'on sait d'avance combien d'étapes il faut.
La méthode de Newton
La méthode de Newton remplace la courbe par sa tangente. En partant d'une valeur x₀, on trace la tangente au point d'abscisse x₀ ; elle coupe l'axe des abscisses en x₁, plus proche de la solution ; on recommence. L'équation de la tangente (chapitre 2) donne la formule :
xₙ₊₁ = xₙ − f(xₙ) / f′(xₙ)
from math import exp
def f(x):
return exp(x) + x - 3
def derivee_f(x):
return exp(x) + 1
def newton(f, df, x0, n):
"""Calcule n itérations de la méthode de Newton à partir de x0."""
x = x0
for i in range(1, n + 1):
x = x - f(x) / df(x)
print(i, x)
return x
newton(f, derivee_f, 1, 4)
1 0.8068242641099854
2 0.7921349596563866
3 0.7920599703659901
4 0.792059968430677
En trois itérations, Newton donne α à 10⁻⁸ près ; la dichotomie demande 27 étapes pour la même précision (log₂(10⁸) ≈ 26,6). En contrepartie, il faut connaître f′, et un mauvais point de départ (près d'un point où f′ s'annule) peut faire diverger la méthode.
| Méthode | Ce qu'il faut | Vitesse | Risque |
|---|---|---|---|
| Balayage | f et un pas | Lente : 10 calculs par décimale | Rater deux solutions proches si le pas est trop grand |
| Dichotomie | f continue, un changement de signe | Une décimale toutes les 3 ou 4 étapes | Aucun, si les hypothèses sont vérifiées |
| Newton | f et f′, un bon point de départ | Le nombre de décimales justes double environ à chaque étape | Diverger si le départ est mal choisi |
Approcher une intégrale : rectangles et point milieu
Pour approcher ∫ₐᵇ f(x) dx, on découpe [a ; b] en n tranches de largeur h = (b − a)/n et on remplace l'aire sous la courbe, sur chaque tranche, par celle d'un rectangle. Dans la méthode du point milieu, la hauteur du rectangle est la valeur de f au milieu de la tranche :
∫ₐᵇ f(x) dx ≈ h × [f(a + h/2) + f(a + 3h/2) + … + f(b − h/2)]
La méthode des trapèzes
Dans la méthode des trapèzes, on relie les points de la courbe aux bords de chaque tranche par un segment : chaque tranche devient un trapèze, d'aire h × (f(gauche) + f(droite))/2. En additionnant, les valeurs intérieures comptent deux fois :
∫ₐᵇ f(x) dx ≈ h × [f(a)/2 + f(a + h) + f(a + 2h) + … + f(b − h) + f(b)/2]
La méthode de Monte-Carlo
La méthode de Monte-Carlo tire des points au hasard dans un rectangle qui contient le domaine, et compte la proportion qui tombe sous la courbe. Cette proportion, multipliée par l'aire du rectangle, approche l'intégrale. Elle est peu précise, mais elle se généralise facilement aux domaines compliqués et aux dimensions supérieures.
Programmer les trois méthodes en Python
Chaque méthode tient en quelques lignes. Le programme ci-dessous les compare sur ∫₀¹ e^(−x²) dx.
from math import exp
import random
def f(x):
return exp(-x ** 2)
def point_milieu(f, a, b, n):
"""Somme des aires de n rectangles dont la hauteur est prise au milieu de chaque tranche."""
h = (b - a) / n
s = 0
for i in range(n):
s = s + f(a + (i + 0.5) * h)
return s * h
def trapezes(f, a, b, n):
"""Somme des aires de n trapèzes."""
h = (b - a) / n
s = (f(a) + f(b)) / 2
for i in range(1, n):
s = s + f(a + i * h)
return s * h
def monte_carlo(f, a, b, ymax, n):
"""Proportion de n points tirés au hasard dans le rectangle [a ; b] x [0 ; ymax]
qui tombent sous la courbe, multipliée par l'aire du rectangle.
Précondition : 0 <= f(x) <= ymax sur [a ; b]."""
dessous = 0
for _ in range(n):
x = random.uniform(a, b)
y = random.uniform(0, ymax)
if y <= f(x):
dessous = dessous + 1
return dessous / n * (b - a) * ymax
for n in (4, 10, 100):
print(n, point_milieu(f, 0, 1, n), trapezes(f, 0, 1, n))
random.seed(2026)
print(monte_carlo(f, 0, 1, 1, 100_000))
4 0.7487471318910093 0.7429840978003812
10 0.7471308777479975 0.7462107961317495
100 0.7468271984923199 0.7468180014679697
0.75041
La valeur exacte, au millionième, est 0,746 824. Comparons :
| Méthode | n = 4 | n = 10 | n = 100 |
|---|---|---|---|
| Point milieu | 0,748 7 | 0,747 1 | 0,746 827 |
| Trapèzes | 0,743 0 | 0,746 2 | 0,746 818 |
| Monte-Carlo (100 000 points) | 0,750 |
- Avec 100 tranches, le point milieu et les trapèzes ont cinq décimales justes. Multiplier n par 10 divise l'erreur par environ 100.
- Ici, le point milieu est un peu plus précis que les trapèzes, et les deux erreurs sont de signes contraires : la valeur exacte est encadrée.
- Monte-Carlo, avec 100 000 points, se trompe encore d'environ 0,004, et son résultat change à chaque exécution (la ligne
random.seed(2026)fixe le tirage pour que tu obtiennes le même nombre que ce cours).
Exercices
Exercice 1 sur 5 Une dichotomie à la main Réussi À revoir
On cherche la solution positive de x² − 2 = 0, c'est-à-dire √2, par dichotomie sur [1 ; 2].
- Fais trois étapes en notant à chaque fois le milieu m, le signe de f(m) et le nouvel intervalle.
- Quel encadrement de √2 obtiens-tu ?
Voir la réponseMasquer la réponse de l'exercice 1
f(1) = −1 < 0 et f(2) = 2 > 0.
| Étape | Intervalle | m | f(m) | Nouvel intervalle |
|---|---|---|---|---|
| 1 | [1 ; 2] | 1,5 | 0,25 > 0 | [1 ; 1,5] |
| 2 | [1 ; 1,5] | 1,25 | −0,437 5 < 0 | [1,25 ; 1,5] |
| 3 | [1,25 ; 1,5] | 1,375 | −0,109 375 < 0 | [1,375 ; 1,5] |
Donc 1,375 ≤ √2 ≤ 1,5. (√2 ≈ 1,414.)
Tu avais trouvé ?
Exercice 2 sur 5 Combien d'étapes ? Réussi À revoir
On cherche par dichotomie une solution d'une équation sur [0 ; 4], avec une précision de 10⁻³. Combien d'étapes faut-il ?
Voir la réponseMasquer la réponse de l'exercice 2
Il faut 4/2ⁿ ≤ 10⁻³, soit 2ⁿ ≥ 4 000, n ≥ log₂ 4 000 ≈ 11,97. Il faut 12 étapes. Vérification : 2¹¹ = 2 048 < 4 000 ≤ 4 096 = 2¹².
Tu avais trouvé ?
Exercice 3 sur 5 Newton pour une racine carrée Réussi À revoir
On applique la méthode de Newton à f(x) = x² − 5 pour approcher √5.
- Montre que la formule devient xₙ₊₁ = (xₙ + 5/xₙ)/2.
- Calcule x₁, x₂ et x₃ en partant de x₀ = 2.
Voir la réponseMasquer la réponse de l'exercice 3
- f′(x) = 2x, donc xₙ₊₁ = xₙ − (xₙ² − 5)/(2xₙ) = (2xₙ² − xₙ² + 5)/(2xₙ) = (xₙ² + 5)/(2xₙ) = (xₙ + 5/xₙ)/2.
- x₁ = (2 + 2,5)/2 = 2,25 ; x₂ = (2,25 + 5/2,25)/2 ≈ 2,236 111 ; x₃ ≈ 2,236 068. √5 ≈ 2,236 068 : trois itérations suffisent pour six décimales.
Tu avais trouvé ?
Exercice 4 sur 5 Trapèzes à la main Réussi À revoir
- Applique la méthode des trapèzes à ∫₀² x² dx avec 2 tranches.
- Compare avec la valeur exacte. L'approximation est-elle trop grande ou trop petite ? Pourquoi ?
Voir la réponseMasquer la réponse de l'exercice 4
- h = 1. Approximation : 1 × [f(0)/2 + f(1) + f(2)/2] = 0 + 1 + 2 = 3.
- Valeur exacte : [x³/3]₀² = 8/3 ≈ 2,667. L'approximation est trop grande de 1/3 : la parabole est convexe, c'est-à-dire qu'entre deux de ses points elle passe sous le segment qui les relie. Les côtés obliques des trapèzes sont donc au-dessus de la courbe.
Tu avais trouvé ?
Exercice 5 sur 5 Programmer les rectangles à gauche Réussi À revoir
La méthode des rectangles « à gauche » prend pour hauteur de chaque rectangle la valeur de f au bord gauche de la tranche. Écris une fonction Python rectangles_gauche(f, a, b, n) et teste-la sur ∫₀² x² dx avec n = 100.
Voir la réponseMasquer la réponse de l'exercice 5
def rectangles_gauche(f, a, b, n):
h = (b - a) / n
s = 0
for i in range(n):
s = s + f(a + i * h) # bord gauche de la tranche i
return s * h
print(rectangles_gauche(lambda x: x ** 2, 0, 2, 100))
Le programme affiche environ 2,626 8, pour une valeur exacte de 2,666 7 : l'erreur, 0,04, est bien plus grande qu'avec le point milieu ou les trapèzes. Pour une fonction croissante, les rectangles à gauche sont tous sous la courbe : l'approximation est trop petite.
Tu avais trouvé ?