Applications : algorithmes numériques de base
Cours · Python (école d'ingénieur), chapitre 10 · école d'ingénieur, informatique · le début du chapitre, la suite sur Adloun
10.1 Introduction et Motivation
Maintenant que nous maîtrisons les bases de Python ainsi que les structures conditionnelles, itératives, et les bibliothèques NumPy et Matplotlib, nous pouvons aborder nos premiers algorithmes de calcul numérique. Contrairement aux calculs sur le type int (précision arbitraire en Python), les calculs sur le type float comportent de nombreuses approximations dues au codage binaire. Ce chapitre explore comment concevoir des algorithmes robustes aux erreurs d'arrondis en abordant la comparaison de flottants, la résolution stable du second degré, la recherche de racines par dichotomie (bisection) et les méthodes classiques d'intégration numérique par quadrature.
10.2 Égalité de Flottants et Tolérances
Comme vu au Chapitre 3, deux calculs mathématiquement identiques peuvent produire des flottants légèrement différents en machine (ex. 0.1 + 0.2 != 0.3). Il est donc extrêmement risqué de baser la terminaison d'une boucle ou un test de validité sur une égalité stricte x == y.
10.2.1 Erreur Absolue vs Erreur Relative
Pour définir si deux flottants et sont proches, on peut employer :
- Une tolérance absolue : . Ce critère est inadapté si les nombres comparés sont très petits devant ou au contraire extrêmement grands.
- Une tolérance relative : . Ce critère résout le problème d'échelle mais présente deux défauts : il n'est pas symétrique (on peut avoir mais ) et il échoue lorsque et sont proches de 0 ou de signes opposés.
En pratique, on combine les deux approches :
numpy.isclose(x, y): (par défaut , )math.isclose(x, y)(Python 3.5+) : (par défaut , )
import math
print(0.1 + 0.2 == 0.3) # False
print(math.isclose(0.1 + 0.2, 0.3)) # True (tolérance par défaut)
print(math.isclose(0.1 + 0.2, 0.3, rel_tol=1e-10, abs_tol=1e-12))
10.3 Application : Résolution Stable du Second Degré
Le problème de l'égalité approchée se pose lors du calcul du discriminant d'une équation .
10.3.1 Le Problème de la Cancellation
Soit l'équation (où le discriminant théorique est nul, , admettant une racine double ).
- L'évaluation naïve donne , conduisant à deux racines simples erronées.
- Pour l'équation ( théoriquement), la machine calcule , concluant faussement à l'absence de solution réelle.
10.3.2 Solution Numérique Stable
Pour corriger ce défaut, nous devons tester la proximité à zéro de relativement au terme . En posant une tolérance égale à l'epsilon machine (), la condition d'égalité à zéro devient :
import math
def solve_quadratique_stable(a, b, c, eps=2**(-52)):
"""
Resout ax^2 + bx + c = 0 de maniere numeriquement stable.
"""
if abs(a) < 1e-15: # Cas dégénéré (équation linéaire)
if abs(b) < 1e-15:
return None # Pas d'équation
return [-c / b]
delta = b * b - 4 * a * c
seuil = eps * b * b # Tolérance relative à b²
if delta < -seuil:
return [] # Pas de racine réelle
elif delta > seuil:
sqrt_delta = math.sqrt(delta)
# Formule stable (évite la cancellation pour la grande racine)
if b >= 0:
x1 = (-b - sqrt_delta) / (2 * a)
x2 = (2 * c) / (-b - sqrt_delta)
else:
x1 = (-b + sqrt_delta) / (2 * a)
x2 = (2 * c) / (-b + sqrt_delta)
return sorted([x1, x2])
else:
# Racine double (discriminant proche de zéro)
return [-b / (2 * a)]
# Test
print(solve_quadratique_stable(0.01, 0.2, 1)) # [-10.0]
print(solve_quadratique_stable(1, -3, 2)) # [1.0, 2.0]
10.4 Recherche de Racine par Dichotomie
La méthode de dichotomie (bisection) est un algorithme robuste permettant de trouver une solution approchée à l'équation pour une fonction continue sur un intervalle .
10.4.1 Principe et Algorithme
Le théorème des valeurs intermédiaires (TVI) assure que si et sont de signes opposés (), alors il existe au moins une racine telle que .
L'algorithme de dichotomie construit deux suites de bornes et telles que :
- Initialisation : et .
- À chaque étape, on calcule le point milieu .
- Si , la racine se trouve dans la moitié gauche : , .
- Sinon, elle est dans la moitié droite : , .
10.4.2 Analyse de l'Erreur et Convergence
La largeur de l'intervalle est divisée par 2 à chaque étape :
L'invariant de boucle est , ce qui garantit la présence d'une racine dans .
Si l'on s'arrête lorsque , alors l'approximation finale vérifie .
Le nombre d'itérations nécessaire pour atteindre cette précision satisfait :
10.4.3 Implémentation Python Sécurisée
def dichotomie(f, a, b, epsilon=1e-12, maxiter=100):
"""
Recherche une racine de f par dichotomie sur [a, b].
Paramètres:
f : fonction continue
a, b : bornes de l'intervalle (f(a)*f(b) <= 0)
epsilon : précision souhaitée
maxiter : nombre maximal d'itérations
Retourne:
Approximation de la racine
"""
if f(a) * f(b) > 0:
raise ValueError("f(a) et f(b) doivent être de signes opposés")
u, v = a, b
for n in range(maxiter):
w = (u + v) / 2
if abs(v - u) <= 2 * epsilon:
return w
if f(u) * f(w) <= 0:
v = w
else:
u = w
raise RuntimeError(f"Non convergence après {maxiter} itérations")
# Exemple : racine de x^2 - 2 (sqrt(2)) sur [1, 2]
f = lambda x: x**2 - 2
racine = dichotomie(f, 1, 2, epsilon=1e-12)
print(f"sqrt(2) = {racine:.12f}")
10.4.4 Méthode de Newton (Convergence Quadratique)
Lorsque la dérivée est disponible, la méthode de Newton offre une convergence quadratique.
def newton(f, df, x0, epsilon=1e-12, maxiter=100):
"""
Recherche une racine de f par la méthode de Newton.
Paramètres:
f : fonction
df : dérivée de f
x0 : approximation initiale
epsilon : précision souhaitée
maxiter : nombre maximal d'itérations
"""
x = x0
for n in range(maxiter):
fx = f(x)
if abs(fx) < epsilon:
return x
dfx = df(x)
if abs(dfx) < 1e-15:
raise RuntimeError("Dérivée nulle")
x = x - fx / dfx
raise RuntimeError(f"Non convergence après {maxiter} itérations")
# Exemple : sqrt(2) par Newton
f = lambda x: x**2 - 2
df = lambda x: 2*x
racine_newton = newton(f, df, 1.5)
print(f"sqrt(2) (Newton) = {racine_newton:.12f}")
10.4.5 Utilisation de SciPy
from scipy.optimize import bisect, newton
# Dichotomie SciPy
racine_bisect = bisect(lambda x: x**2 - 2, 1, 2, xtol=1e-12)
# Newton SciPy
racine_newton_sp = newton(lambda x: x**2 - 2, 1.5)
print(f"SciPy bisect : {racine_bisect:.12f}")
print(f"SciPy newton : {racine_newton_sp:.12f}")
10.5 Intégration Numérique (Méthodes de Quadrature)
Le calcul analytique d'une intégrale définie est parfois complexe ou impossible. Les méthodes de quadrature approchent cette intégrale par une somme pondérée finie de valeurs de la fonction :
Pour calculer l'intégrale sur un grand intervalle , on le subdivise en sous-intervalles de taille délimités par les points (ou selon la notation).
10.5.1 Méthode du Rectangle (Gauche et Droite)
La méthode du rectangle à gauche sur un intervalle élémentaire approxime la fonction par sa valeur sur la borne inférieure :
La méthode du rectangle à droite utilise la borne supérieure :
Si est de classe sur , alors l'erreur vérifie :
où .
Formules composites :
- Rectangle à gauche :
où . L'erreur globale est en : .
- Rectangle à droite :
def rectangle_gauche(f, a, b, n):
h = (b - a) / n
x = np.linspace(a, b - h, n)
return h * np.sum(f(x))
def rectangle_droit(f, a, b, n):
h = (b - a) / n
x = np.linspace(a + h, b, n)
return h * np.sum(f(x))
10.5.2 Méthode du Point Milieu
La méthode du point milieu approche l'intégrale en évaluant la fonction au centre de l'intervalle :
Si est de classe sur , alors l'erreur vérifie :
où . La méthode est d'ordre 2.
Formule composite :
L'erreur globale est en : .
def point_milieu(f, a, b, n):
h = (b - a) / n
x = np.linspace(a + h/2, b - h/2, n)
return h * np.sum(f(x))
10.5.3 Méthode des Trapèzes
La méthode des trapèzes approxime la fonction par la fonction affine joignant et :
Si est de classe sur , alors l'erreur vérifie :
La méthode est d'ordre 2.
Formule composite :
L'erreur globale est en : .
def trapezes(f, a, b, n):
h = (b - a) / n
x = np.linspace(a, b, n+1)
return h * (np.sum(f(x)) - (f(a) + f(b))/2)
10.5.4 Méthode de Simpson
La méthode de Simpson approche la fonction par le polynôme de degré 2 passant par , et :
Bien que basée sur une interpolation quadratique (degré 2), la méthode de Simpson est d'ordre 4 (exacte pour les polynômes de degré ). Si est de classe sur , alors :
où .
Formule composite ( doit être pair) :
L'erreur globale est en : .
La suite du cours est sur Adloun
Le chapitre en entier, formules et figures comprises, avec le tuteur, les fiches, les QCM et les exercices.
Lire la suite du coursEn accès libre, sans inscription.