Erreurs dans les opérations flottantes
Avec la leçon précédente, nous savons maintenant que seul un sous-ensemble fini des réels peut être stocké exactement et nous connaissons la structure IEEE 754. Cette leçon explore les conséquences pratiques de cette limitation : comment les erreurs apparaissent lors des calculs et comment elles se propagent à travers les opérations arithmétiques.
Troncature versus arrondissement
Lorsqu'un nombre réel possède plus de chiffres significatifs que le système ne peut en stocker, il faut le projeter sur l'ensemble des nombres machine. Deux stratégies principales existent.
Notation
Soit un système flottant avec :
- : la base
- : le nombre de chiffres significatifs (précision)
- : les bornes de l'exposant
Tout nombre réel peut s'écrire en notation flottante normalisée :
On note la représentation flottante de dans le système.
Troncature (arrondi vers zéro)
La troncature consiste à ignorer les chiffres au-delà de la position . C'est équivalent à un arrondi vers zéro.
Définition formelle : Soit . La troncature est :
Borne d'erreur absolue : L'erreur de troncature est bornée par :
Borne d'erreur relative : Pour :
Cette borne est l'epsilon machine .
Lien avec IEEE 754
Pour IEEE 754 en base :
- Simple précision : bits (23 stockés + 1 implicite), donc
- Double précision : bits (52 stockés + 1 implicite), donc
Démonstration appliquée : troncature
Exemple 1 : Tronquer dans un système .
Étape 1 : Écrire en notation flottante normalisée.
Étape 2 : Identifier les chiffres de la mantisse.
Étape 3 : Conserver uniquement les premiers chiffres.
Étape 4 : Calculer l'erreur et vérifier la borne.
Vérifions la borne : . Notre erreur de 0,566% est bien inférieure.
Exemple 2 : Tronquer dans un système .
Étape 1 : Normaliser.
Étape 2 : Identifier les chiffres.
Étape 3 : Tronquer à chiffres.
Étape 4 : Calculer l'erreur.
Propriété fondamentale : La troncature est biaisée puisque :
En d'autres termes, la troncature rapproche toujours vers zéro.
Arrondissement au plus proche (round to nearest)
L'arrondissement au plus proche projette un nombre réel sur le nombre machine le plus proche, minimisant ainsi l'erreur.
Définition formelle : Soit un réel et les deux nombres machine encadrant (avec ). L'arrondi au plus proche est :
Borne d'erreur relative : Pour l'arrondissement au plus proche :
où est l'epsilon machine. Cette borne est deux fois plus petite que pour la troncature.
Procédure pratique (ajout de demi-unité) :
Soit en notation normalisée (avec ).
Méthode 1 — Sur la mantisse : Ajouter à la mantisse, puis tronquer :
Méthode 2 — Sur le nombre : Ajouter au nombre, puis tronquer :
Comprendre la demi-unité
D'où vient la formule ?
Dans un système , les nombres machine avec exposant ont la forme où .
Deux nombres machine consécutifs (même exposant) diffèrent d'une unité au -ème chiffre de la mantisse. Ce chiffre est à la position après la virgule, c'est-à-dire :
Par exemple, pour : le 3ème chiffre est à la position .
L'écart entre mantisses est donc , et l'écart entre les nombres (en multipliant par ) est :
Pour arrondir au plus proche, on ajoute la moitié de cet écart :
Exemple numérique : Pour avec :
- Exposant :
- Les mantisses voisines (à chiffres) sont et
- Le 3ème chiffre est à la position , donc l'écart entre mantisses est
- Écart entre nombres machine :
- Demi-unité : ✓
Note sur les conventions : Certains ouvrages utilisent une convention différente où la mantisse est de la forme avec . Dans ce cas, l'exposant est décalé de 1, et la formule devient . Le résultat final est le même.
Démonstration appliquée : arrondissement
Exemple 1 : Arrondir dans un système .
Étape 1 : Normaliser.
Étape 2 : Identifier les nombres machine encadrants.
Avec chiffres significatifs, les nombres machine autour de 1237 sont :
L'écart entre eux est , donc la demi-unité est .
Étape 3 : Appliquer la méthode d'ajout de demi-unité.
Étape 4 : Tronquer.
Vérification : 1237 est à distance 7 de 1230 et à distance 3 de 1240. Le plus proche est bien 1240. ✓
Étape 5 : Calculer l'erreur et vérifier la borne.
Vérifions la borne : . Notre erreur de 0,243% est bien inférieure. ✓
Exemple 2 : Arrondir dans un système .
Étape 1 : Normaliser.
Les nombres machine encadrants sont toujours 1230 et 1240.
Étape 2 : Ajouter la demi-unité (5).
Étape 3 : Tronquer.
Vérification : 1234 est à distance 4 de 1230 et à distance 6 de 1240. Le plus proche est bien 1230. ✓
Étape 4 : L'erreur est de 4, soit (toujours sous la borne de 0,5%).
Comparaison des méthodes
| Nombre x | Troncature | Erreur | Arrondissement | Erreur |
|---|---|---|---|---|
Observations :
- La troncature produit toujours une erreur de même signe que (vers zéro)
- L'arrondissement produit des erreurs positives ou négatives selon le cas
- L'erreur maximale par arrondissement est environ la moitié de celle par troncature
Récapitulatif des bornes d'erreur
| Méthode | Borne d'erreur relative | Propriété |
|---|---|---|
| Troncature | Biaisée (vers zéro) | |
| Arrondi au plus proche | Non biaisée |
En pratique : les modes d'arrondi IEEE 754
Tous les processeurs modernes implémentent la norme IEEE 754. Cette norme définit 5 modes d'arrondi :
| Mode | Description | Usage |
|---|---|---|
| Round to nearest, ties to even | Arrondi au plus proche, égalité → pair | Défaut |
| Round to nearest, ties away | Arrondi au plus proche, égalité → loin de 0 | Rare |
| Round toward | Arrondi vers le haut | Arithmétique d'intervalles |
| Round toward | Arrondi vers le bas | Arithmétique d'intervalles |
| Round toward 0 | Troncature | Conversion float → entier |
Règle du pair (ties to even)
Quand un nombre est exactement au milieu de deux nombres machine, IEEE 754 arrondit vers celui dont le dernier bit est pair. Cette règle élimine un biais subtil qui apparaîtrait si on arrondissait toujours vers le haut en cas d'égalité.
Exemple : 1,5 est au milieu de 1 et 2 → on arrondit à 2 (pair). Mais 2,5 au milieu de 2 et 3 → on arrondit aussi à 2 (pair).
Le mode par défaut est l'arrondi au plus proche (« round to nearest, ties to even »). C'est ce qu'utilisent votre ordinateur, votre téléphone, et pratiquement tout appareil numérique pour les opérations flottantes.
Pourquoi l'arrondi par défaut et pas la troncature ? La troncature introduit un biais systématique : les résultats sont toujours décalés vers zéro. Sur des millions d'opérations, ce biais s'accumule et fausse les résultats. L'arrondi au plus proche n'a pas ce biais — les erreurs positives et négatives se compensent statistiquement.
Quand la troncature est-elle utilisée ? La troncature (« round toward 0 ») n'est pas utilisée pour les opérations flottantes standard, mais elle intervient généralement dans deux cas :
- Conversion float → entier :
int(3.7)en Python ou(int)3.7en C donne3. La partie fractionnaire est supprimée. - Mode explicitement activé : le programmeur peut changer le mode d'arrondi pour des besoins spécifiques (arithmétique d'intervalles, etc.).
Comportement des quatre opérations
En arithmétique flottante, les opérations classiques ne donnent généralement pas le résultat mathématiquement exact. La norme IEEE 754 exige cependant que chaque opération soit correctement arrondie : le résultat doit être celui qu'on obtiendrait en calculant avec une précision infinie, puis en arrondissant.
Notation et modèle d'erreur
Soit une opération arithmétique. On note :
- : le résultat exact (réel)
- : le résultat flottant calculé
Modèle standard (IEEE 754) : Pour toute opération entre deux nombres flottants et :
où est l'epsilon machine.
Comment lire cette formule ?
Cette formule exprime que le résultat flottant est légèrement perturbé par rapport au résultat exact :
- est le résultat mathématiquement exact (ce qu'on obtiendrait avec une précision infinie)
- est le résultat stocké par l'ordinateur (arrondi)
- est la petite erreur relative introduite par l'arrondi
Multiplier par revient à dire que le résultat est décalé d'un facteur proportionnel à lui-même. Par exemple, si et le résultat exact est 3,14159, alors le résultat flottant sera environ .
L'erreur absolue est petite, mais l'erreur relative (le rapport erreur/valeur) est toujours bornée par .
Bornes d'erreur par opération
| Opération | Notation | Borne d'erreur relative |
|---|---|---|
| Addition | ||
| Soustraction | ||
| Multiplication | ||
| Division |
Les symboles représentent les opérations flottantes (calculées), par opposition aux opérations exactes .
Attention : erreurs d'entrée
Si les opérandes et sont eux-mêmes des approximations de valeurs réelles et , l'erreur totale combine l'erreur d'arrondi de l'opération et les erreurs déjà présentes dans les opérandes.
Démonstration appliquée : Addition
Calculons dans un système .
Étape 1 : Représenter les opérandes en notation flottante normalisée
Étape 2 : Aligner les exposants
Pour additionner, on exprime les deux nombres avec le même exposant (le plus grand) :
Étape 3 : Effectuer l'addition exacte
Étape 4 : Arrondir à chiffres
Le résultat exact doit être arrondi. En notation normalisée : .
Par troncature :
Par arrondissement (demi-unité = 0,005) :
Bilan et vérification du modèle :
- Valeur exacte :
- Par arrondissement :
- Erreur relative :
- Borne théorique :
L'erreur respecte bien la borne du modèle IEEE 754.
Démonstration appliquée : Multiplication
Calculons dans un système .
Étape 1 : Représenter les opérandes
Note : n'est pas représentable exactement ; on a déjà une erreur d'entrée.
Étape 2 : Multiplier les mantisses
Étape 3 : Additionner les exposants
Résultat intermédiaire :
Étape 4 : Normaliser et arrondir
Le résultat est déjà normalisé et a exactement 3 chiffres. Pas d'arrondi supplémentaire.
Bilan : Le résultat mathématique devrait être , mais l'arithmétique flottante donne . L'erreur provient de la représentation initiale de , pas de l'opération de multiplication elle-même.
Erreur d'entrée vs erreur d'opération
Cet exemple illustre la différence entre :
- L'erreur d'arrondi de l'opération (bornée par )
- L'erreur d'entrée (ici, n'est pas représentable exactement)
L'erreur totale peut excéder à cause des erreurs d'entrée.
Perte de précision
Certaines configurations de calcul amplifient dramatiquement les erreurs.
Le phénomène d'absorption
L'epsilon machine explique pourquoi certains calculs semblent « ignorer » de petites quantités :
# Phénomène d'absorption
grand = 1e16
petit = 1.0
resultat = grand + petit - grand
print(f"(1e16 + 1) - 1e16 = {resultat}") # Devrait être 1, mais...
# Explication : 1.0 est trop petit par rapport à 1e16
# pour affecter sa représentation flottante
print(f"1e16 + 1 == 1e16 : {1e16 + 1 == 1e16}")Ce phénomène s'appelle l'absorption : un petit nombre ajouté à un grand nombre peut être « absorbé » sans modifier le résultat.
Démonstration appliquée : Absorption
Calculons dans un système .
Étape 1 : Représenter les opérandes en notation normalisée
Étape 2 : Aligner les exposants
Pour soustraire, on exprime avec l'exposant de :
Étape 3 : Effectuer la soustraction exacte
Résultat exact :
Étape 4 : Arrondir à chiffres
Par troncature :
Par arrondissement :
Observation : Par arrondissement, le résultat est identique à l'opérande initial ! Le petit nombre a été complètement « absorbé ». C'est un cas typique où alors que .
Perte d'associativité
En mathématiques, l'addition est associative :
En arithmétique flottante, cette propriété n'est plus garantie.
# Démonstration de la perte d'associativité
a = 1e16
b = -1e16
c = 1.0
# Ordre 1 : (a + b) + c
resultat1 = (a + b) + c
print(f"(1e16 + (-1e16)) + 1 = {resultat1}")
# Ordre 2 : a + (b + c)
resultat2 = a + (b + c)
print(f"1e16 + ((-1e16) + 1) = {resultat2}")
print(f"Les résultats sont égaux : {resultat1 == resultat2}")Dans le premier cas, exactement, puis .
Dans le second cas, (le 1 est absorbé), puis .
Règle critique
L'ordre des opérations affecte le résultat en arithmétique flottante. Pour maximiser la précision, il est généralement préférable d'additionner d'abord les termes de même ordre de grandeur, en commençant par les plus petits.
Perte de commutativité de la multiplication
La multiplication aussi peut perdre sa commutativité dans des cas extrêmes :
# Note sur les exposants en Python (double précision IEEE 754):
# - Exposant min (min_exp): -1021 (en base 2), soit environ 10^-307 (min_10_exp)
# - Exposant max (max_exp): 1024 (en base 2), soit environ 10^308 (max_10_exp)
# Le biais est de 1023, donc l'exposant réel va de -1022 à +1023 pour les nombres normalisés.
# Pour voir toutes les infos: import sys; print(sys.float_info)
# La multiplication reste généralement commutative,
# mais l'ordre peut affecter les résultats intermédiaires
a = 1e-307
b = 1e308 ## essayer aussi avec 1e306, 1e307, 1e308, 1e309
c = 2.0
# Ordre 1
r1 = (a * b) * c
print(f"({a} * {b}) * {c} = {r1}")
# Ordre 2 : risque de dépassement intermédiaire
r2 = (b * c) * a
print(f"({b} * {c}) * {a} = {r2}")
# Ordre 3 : risque de soupassement intermédiaire
r3 = (a * c) * b
print(f"({a} * {c}) * {b} = {r3}")Résultats intermédiaires
Pour toute suite d'opérations, chaque résultat intermédiaire est arrondi (ou tronqué) avant d'être utilisé dans l'opération suivante. Les erreurs s'accumulent donc à chaque étape.
Résumé des pièges courants
| Piège | Cause | Conséquence |
|---|---|---|
| Absorption | Addition de nombres d'ordres très différents | Le petit nombre est « ignoré » |
| Perte d'associativité | Ordres de grandeur variés | Résultat dépend de l'ordre des opérations |
| Accumulation d'erreurs | Longues chaînes de calculs | Erreur finale peut être très grande |
| Dépassement/soupassement | Résultats hors plage | Inf, 0 ou NaN |
Annulation catastrophique
Un piège particulièrement dangereux est l'annulation catastrophique : la soustraction de deux nombres très proches provoque une perte massive de chiffres significatifs. Ce phénomène est si important qu'il fait l'objet d'une leçon dédiée.
Ce qu'il faut retenir
L'arithmétique flottante n'est pas l'arithmétique des réels. Les propriétés mathématiques fondamentales (associativité, distributivité) ne sont plus garanties. Les phénomènes d'absorption et de décalage peuvent causer des pertes de précision significatives.
Formules essentielles
Bornes d'erreur pour la représentation :
Modèle standard pour les opérations (IEEE 754) :
Points essentiels
- La troncature est biaisée (vers zéro), l'arrondissement minimise l'erreur moyenne
- Chaque opération flottante () introduit une erreur relative bornée par
- L'absorption fait disparaître les petites quantités ajoutées aux grandes
- L'ordre des opérations affecte le résultat final (perte d'associativité)
- Les erreurs s'accumulent au fil des calculs
La prochaine leçon introduira les outils pour mesurer ces erreurs : les chiffres significatifs exacts.
Exercices de réflexion
Exercice 1 : Ordre des opérations
Considérez les trois nombres : , , .
- Calculez à la main en arithmétique exacte.
- Calculez à la main en arithmétique exacte.
- Expliquez pourquoi Python donne des résultats différents pour ces deux expressions.
- Généralisez : quelle règle devrait-on suivre pour minimiser les erreurs lors de sommations ?
Exercice 2 : Troncature vs arrondissement
Dans un système flottant fictif avec et chiffres de mantisse, calculez les représentations par troncature et par arrondissement des nombres suivants :
Pour chaque cas :
- Normalisez le nombre sous la forme
- Calculez et
- Vérifiez que les erreurs relatives respectent les bornes et
Indice
Rappel des bornes pour : .
Exercice 3 : Absorption en pratique
Écrivez un programme Python qui :
- Calcule la somme (un million de termes )
- Compare le résultat avec la valeur théorique
- Propose une méthode pour obtenir un résultat plus précis
Exercice 4 : Multiplication et précision
Dans un système , calculez pas à pas le produit .
- Représentez chaque opérande en notation flottante normalisée.
- Effectuez la multiplication des mantisses.
- Additionnez les exposants.
- Renormalisez si nécessaire.
- Arrondissez à 3 chiffres.
- Comparez avec le résultat exact.