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 F(b,s,m,M)\mathbb{F}(b, s, m, M) un système flottant avec :

  • bb : la base
  • ss : le nombre de chiffres significatifs (précision)
  • m,Mm, M : les bornes de l'exposant

Tout nombre réel x0x \neq 0 peut s'écrire en notation flottante normalisée :

x=±d1,d2d3dsds+1mantisse×beavec d10x = \pm \underbrace{d_1{,}d_2 d_3 \cdots d_s d_{s+1} \cdots}_{\text{mantisse}} \times b^e \quad \text{avec } d_1 \neq 0

On note fl(x)\text{fl}(x) la représentation flottante de xx dans le système.

Troncature (arrondi vers zéro)

La troncature consiste à ignorer les chiffres au-delà de la position ss. C'est équivalent à un arrondi vers zéro.

Définition formelle : Soit x=±d1,d2dsds+1×bex = \pm d_1{,}d_2 \cdots d_s d_{s+1} \cdots \times b^e. La troncature est :

tron(x,s)=±d1,d2d3ds×be\text{tron}(x, s) = \pm d_1{,}d_2 d_3 \cdots d_s \times b^e

Borne d'erreur absolue : L'erreur de troncature est bornée par :

xtron(x,s)<bes+1|x - \text{tron}(x, s)| < b^{e-s+1}

Borne d'erreur relative : Pour x0x \neq 0 :

xtron(x,s)x<b1s\left| \frac{x - \text{tron}(x, s)}{x} \right| < b^{1-s}

Cette borne b1sb^{1-s} est l'epsilon machine ε\varepsilon.

💡

Lien avec IEEE 754

Pour IEEE 754 en base b=2b = 2 :

  • Simple précision : s=24s = 24 bits (23 stockés + 1 implicite), donc ε=223\varepsilon = 2^{-23}
  • Double précision : s=53s = 53 bits (52 stockés + 1 implicite), donc ε=252\varepsilon = 2^{-52}

Démonstration appliquée : troncature

Exemple 1 : Tronquer x=1237x = 1237 dans un système (b=10,s=3)(b=10, s=3).

Étape 1 : Écrire en notation flottante normalisée.

x=1237=1,237×103x = 1237 = 1{,}237 \times 10^3

Étape 2 : Identifier les chiffres de la mantisse.

d1=1,d2=2,d3=3,d4=7d_1 = 1, \quad d_2 = 2, \quad d_3 = 3, \quad d_4 = 7

Étape 3 : Conserver uniquement les s=3s = 3 premiers chiffres.

tron(1237,3)=1,23×103=1230\text{tron}(1237, 3) = 1{,}23 \times 10^3 = 1230

Étape 4 : Calculer l'erreur et vérifier la borne.

Erreur absolue=1237tron(1237,3)=12371230=7\text{Erreur absolue} = |1237 - \text{tron}(1237, 3)| = |1237 - 1230| = 7
Erreur relative=712370,566%\text{Erreur relative} = \frac{7}{1237} \approx 0{,}566\%

Vérifions la borne : b1s=1013=102=1%b^{1-s} = 10^{1-3} = 10^{-2} = 1\%. Notre erreur de 0,566% est bien inférieure.

Exemple 2 : Tronquer x=0,0098765x = 0{,}0098765 dans un système (b=10,s=3)(b=10, s=3).

Étape 1 : Normaliser.

x=0,0098765=9,8765×103x = 0{,}0098765 = 9{,}8765 \times 10^{-3}

Étape 2 : Identifier les chiffres.

d1=9,d2=8,d3=7,d4=6,d5=5d_1 = 9, \quad d_2 = 8, \quad d_3 = 7, \quad d_4 = 6, \quad d_5 = 5

Étape 3 : Tronquer à s=3s=3 chiffres.

tron(0,0098765,3)=9,87×103=0,00987\text{tron}(0{,}0098765, 3) = 9{,}87 \times 10^{-3} = 0{,}00987

Étape 4 : Calculer l'erreur.

Erreur absolue=0,00987650,00987=0,0000065\text{Erreur absolue} = |0{,}0098765 - 0{,}00987| = 0{,}0000065
Erreur relative=0,00000650,00987650,066%\text{Erreur relative} = \frac{0{,}0000065}{0{,}0098765} \approx 0{,}066\%

Propriété fondamentale : La troncature est biaisée puisque :

tron(x,s)xpour x>0\text{tron}(x, s) \leq x \quad \text{pour } x > 0
tron(x,s)xpour x<0\text{tron}(x, s) \geq x \quad \text{pour } x < 0

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 xx un réel et x,x+x_-, x_+ les deux nombres machine encadrant xx (avec x<x<x+x_- < x < x_+). L'arrondi au plus proche est :

arrondi(x,s)={xsi xx<xx+x+si xx>xx+reˋgle de bris d’eˊgaliteˊsi xx=xx+\text{arrondi}(x, s) = \begin{cases} x_- & \text{si } |x - x_-| < |x - x_+| \\ x_+ & \text{si } |x - x_-| > |x - x_+| \\ \text{règle de bris d'égalité} & \text{si } |x - x_-| = |x - x_+| \end{cases}

Borne d'erreur relative : Pour l'arrondissement au plus proche :

xarrondi(x,s)x12b1s=ε2\left| \frac{x - \text{arrondi}(x, s)}{x} \right| \leq \frac{1}{2} b^{1-s} = \frac{\varepsilon}{2}

ε=b1s\varepsilon = b^{1-s} est l'epsilon machine. Cette borne est deux fois plus petite que pour la troncature.

Procédure pratique (ajout de demi-unité) :

Soit x=±d1,d2dsds+1×bex = \pm d_1{,}d_2 \cdots d_s d_{s+1} \cdots \times b^e en notation normalisée (avec 1d1<b1 \leq d_1 < b).

Méthode 1 — Sur la mantisse : Ajouter 12b1s\frac{1}{2} b^{1-s} à la mantisse, puis tronquer :

mantisse arrondie=tron(d1,d2dsds+1+12×b1s,s)\text{mantisse arrondie} = \text{tron}\left(d_1{,}d_2 \cdots d_s d_{s+1} + \frac{1}{2} \times b^{1-s}, s\right)

Méthode 2 — Sur le nombre : Ajouter 12bes+1\frac{1}{2} b^{e-s+1} au nombre, puis tronquer :

arrondi(x,s)=signe(x)tron(x+12bes+1,s)\text{arrondi}(x, s) = \text{signe}(x) \cdot \text{tron}\left(|x| + \frac{1}{2} b^{e-s+1}, s\right)
💡

Comprendre la demi-unité

D'où vient la formule ?

Dans un système (b,s)(b, s), les nombres machine avec exposant ee ont la forme d1,d2ds×bed_1{,}d_2 \cdots d_s \times b^e1d1<b1 \leq d_1 < b.

Deux nombres machine consécutifs (même exposant) diffèrent d'une unité au ss-ème chiffre de la mantisse. Ce chiffre est à la position 1s1-s après la virgule, c'est-à-dire :

0,00s1 zeˊros1=b1s\underbrace{0{,}0\cdots0}_{s-1 \text{ zéros}}1 = b^{1-s}

Par exemple, pour s=3s = 3 : le 3ème chiffre est à la position 0,01=102=10130{,}01 = 10^{-2} = 10^{1-3}.

L'écart entre mantisses est donc b1sb^{1-s}, et l'écart entre les nombres (en multipliant par beb^e) est :

Δ=b1s×be=bes+1\Delta = b^{1-s} \times b^e = b^{e-s+1}

Pour arrondir au plus proche, on ajoute la moitié de cet écart :

demi-uniteˊ=Δ2=12bes+1\text{demi-unité} = \frac{\Delta}{2} = \frac{1}{2} b^{e-s+1}

Exemple numérique : Pour x=1237=1,237×103x = 1237 = 1{,}237 \times 10^3 avec (b=10,s=3)(b=10, s=3) :

  • Exposant : e=3e = 3
  • Les mantisses voisines (à s=3s=3 chiffres) sont 1,231{,}23 et 1,241{,}24
  • Le 3ème chiffre est à la position 10210^{-2}, donc l'écart entre mantisses est 1013=0,0110^{1-3} = 0{,}01
  • Écart entre nombres machine : 0,01×103=10=bes+1=1033+10{,}01 \times 10^3 = 10 = b^{e-s+1} = 10^{3-3+1}
  • Demi-unité : 102=5=12×1033+1=5\frac{10}{2} = 5 = \frac{1}{2} \times 10^{3-3+1} = 5

Note sur les conventions : Certains ouvrages utilisent une convention différente où la mantisse est de la forme 0,d1d20{,}d_1 d_2 \cdots avec d10d_1 \neq 0. Dans ce cas, l'exposant ee' est décalé de 1, et la formule devient 12bes\frac{1}{2} b^{e'-s}. Le résultat final est le même.

Démonstration appliquée : arrondissement

Exemple 1 : Arrondir x=1237x = 1237 dans un système (b=10,s=3)(b=10, s=3).

Étape 1 : Normaliser.

x=1,237×103(e=3)x = 1{,}237 \times 10^3 \quad (e = 3)

Étape 2 : Identifier les nombres machine encadrants.

Avec s=3s = 3 chiffres significatifs, les nombres machine autour de 1237 sont :

x=1,23×103=1230etx+=1,24×103=1240x_- = 1{,}23 \times 10^3 = 1230 \quad \text{et} \quad x_+ = 1{,}24 \times 10^3 = 1240

L'écart entre eux est x+x=10x_+ - x_- = 10, donc la demi-unité est 55.

Étape 3 : Appliquer la méthode d'ajout de demi-unité.

x=1237+5=1242x^* = 1237 + 5 = 1242

Étape 4 : Tronquer.

arrondi(1237,3)=tron(1242,3)=1,24×103=1240\text{arrondi}(1237, 3) = \text{tron}(1242, 3) = 1{,}24 \times 10^3 = 1240

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.

Erreur absolue=12371240=3\text{Erreur absolue} = |1237 - 1240| = 3
Erreur relative=312370,243%\text{Erreur relative} = \frac{3}{1237} \approx 0{,}243\%

Vérifions la borne : 12b1s=12×102=0,5%\frac{1}{2}b^{1-s} = \frac{1}{2} \times 10^{-2} = 0{,}5\%. Notre erreur de 0,243% est bien inférieure. ✓

Exemple 2 : Arrondir x=1234x = 1234 dans un système (b=10,s=3)(b=10, s=3).

Étape 1 : Normaliser.

x=1,234×103x = 1{,}234 \times 10^3

Les nombres machine encadrants sont toujours 1230 et 1240.

Étape 2 : Ajouter la demi-unité (5).

x=1234+5=1239x^* = 1234 + 5 = 1239

Étape 3 : Tronquer.

arrondi(1234,3)=tron(1239,3)=1,23×103=1230\text{arrondi}(1234, 3) = \text{tron}(1239, 3) = 1{,}23 \times 10^3 = 1230

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 0,324%0{,}324\% (toujours sous la borne de 0,5%).

Comparaison des méthodes

Nombre xTroncatureErreurArrondissementErreur
12371237123012307-712401240+3+3
12341234123012304-4123012304-4
0,00987650{,}00987650,009870{,}009870,0000065-0{,}00000650,009880{,}00988+0,0000035+0{,}0000035

Observations :

  • La troncature produit toujours une erreur de signe opposé à celui de xx (le résultat est ramené vers zéro), avec la convention erreur = valeur approchée − valeur exacte utilisée dans le tableau
  • 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éthodeBorne d'erreur relativePropriété
Troncature<b1s=ε< b^{1-s} = \varepsilonBiaisée (vers zéro)
Arrondi au plus proche12b1s=ε2\leq \frac{1}{2}b^{1-s} = \frac{\varepsilon}{2}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 :

ModeDescriptionUsage
Round to nearest, ties to evenArrondi au plus proche, égalité → pairDéfaut
Round to nearest, ties awayArrondi au plus proche, égalité → loin de 0Rare
Round toward ++\inftyArrondi vers le hautArithmétique d'intervalles
Round toward -\inftyArrondi vers le basArithmétique d'intervalles
Round toward 0TroncatureConversion 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.7 en C donne 3. 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 {+,,×,÷}\circ \in \{+, -, \times, \div\} une opération arithmétique. On note :

  • xyx \circ y : le résultat exact (réel)
  • fl(xy)\text{fl}(x \circ y) : le résultat flottant calculé

Modèle standard (IEEE 754) : Pour toute opération \circ entre deux nombres flottants xx et yy :

fl(xy)=(xy)(1+δ)avec δε2\text{fl}(x \circ y) = (x \circ y)(1 + \delta) \quad \text{avec } |\delta| \leq \frac{\varepsilon}{2}

ε=b1s\varepsilon = b^{1-s} 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 :

  • xyx \circ y est le résultat mathématiquement exact (ce qu'on obtiendrait avec une précision infinie)
  • fl(xy)\text{fl}(x \circ y) est le résultat stocké par l'ordinateur (arrondi)
  • δ\delta est la petite erreur relative introduite par l'arrondi

Multiplier par (1+δ)(1 + \delta) revient à dire que le résultat est décalé d'un facteur proportionnel à lui-même. Par exemple, si δ=1016\delta = 10^{-16} et le résultat exact est 3,14159, alors le résultat flottant sera environ 3,14159×1,00000000000000013,14159+3×10163{,}14159 \times 1{,}0000000000000001 \approx 3{,}14159 + 3 \times 10^{-16}.

L'erreur absolue est petite, mais l'erreur relative (le rapport erreur/valeur) est toujours bornée par ε2\frac{\varepsilon}{2}.

Bornes d'erreur par opération

OpérationNotationBorne d'erreur relative
Additionxy=fl(x+y)x \oplus y = \text{fl}(x + y)δε2|\delta| \leq \frac{\varepsilon}{2}
Soustractionxy=fl(xy)x \ominus y = \text{fl}(x - y)δε2|\delta| \leq \frac{\varepsilon}{2}
Multiplicationxy=fl(x×y)x \otimes y = \text{fl}(x \times y)δε2|\delta| \leq \frac{\varepsilon}{2}
Divisionxy=fl(x÷y)x \oslash y = \text{fl}(x \div y)δε2|\delta| \leq \frac{\varepsilon}{2}

Les symboles ,,,\oplus, \ominus, \otimes, \oslash représentent les opérations flottantes (calculées), par opposition aux opérations exactes +,,×,÷+, -, \times, \div.

⚠️

Attention : erreurs d'entrée

Si les opérandes xx et yy sont eux-mêmes des approximations de valeurs réelles x^\hat{x} et y^\hat{y}, 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 1,370,02691{,}37 \oplus 0{,}0269 dans un système (b=10,s=3)(b=10, s=3).

Étape 1 : Représenter les opérandes en notation flottante normalisée

x=fl(1,37)=1,37×100x = \text{fl}(1{,}37) = 1{,}37 \times 10^0
y=fl(0,0269)=2,69×102y = \text{fl}(0{,}0269) = 2{,}69 \times 10^{-2}

Étape 2 : Aligner les exposants

Pour additionner, on exprime les deux nombres avec le même exposant (le plus grand) :

y=2,69×102=0,0269×100y = 2{,}69 \times 10^{-2} = 0{,}0269 \times 10^0

Étape 3 : Effectuer l'addition exacte

x+y=1,37+0,0269=1,3969x + y = 1{,}37 + 0{,}0269 = 1{,}3969

Étape 4 : Arrondir à s=3s=3 chiffres

Le résultat exact 1,39691{,}3969 doit être arrondi. En notation normalisée : 1,3969×1001{,}3969 \times 10^0.

Par troncature :

tron(1,3969,3)=1,39\text{tron}(1{,}3969, 3) = 1{,}39

Par arrondissement (demi-unité = 0,005) :

1,3969+0,005=1,4019tron(1,4019,3)=1,401{,}3969 + 0{,}005 = 1{,}4019 \Rightarrow \text{tron}(1{,}4019, 3) = 1{,}40

Bilan et vérification du modèle :

  • Valeur exacte : 1,39691{,}3969
  • Par arrondissement : 1,401{,}40
  • Erreur relative : δ=1,401,39691,39690,22%\delta = \frac{1{,}40 - 1{,}3969}{1{,}3969} \approx 0{,}22\%
  • Borne théorique : ε2=1022=0,5%\frac{\varepsilon}{2} = \frac{10^{-2}}{2} = 0{,}5\%

L'erreur respecte bien la borne du modèle IEEE 754.

Démonstration appliquée : Multiplication

Calculons fl(13)3\text{fl}\left(\frac{1}{3}\right) \otimes 3 dans un système (b=10,s=3)(b=10, s=3).

Étape 1 : Représenter les opérandes

x=fl(13)=fl(0,333)=3,33×101x = \text{fl}\left(\frac{1}{3}\right) = \text{fl}(0{,}\overline{333}) = 3{,}33 \times 10^{-1}
y=fl(3)=3,00×100y = \text{fl}(3) = 3{,}00 \times 10^0

Note : 13\frac{1}{3} n'est pas représentable exactement ; on a déjà une erreur d'entrée.

Étape 2 : Multiplier les mantisses

3,33×3,00=9,993{,}33 \times 3{,}00 = 9{,}99

Étape 3 : Additionner les exposants

101×100=10110^{-1} \times 10^0 = 10^{-1}

Résultat intermédiaire : 9,99×101=0,9999{,}99 \times 10^{-1} = 0{,}999

Étape 4 : Normaliser et arrondir

Le résultat 9,99×1019{,}99 \times 10^{-1} est déjà normalisé et a exactement 3 chiffres. Pas d'arrondi supplémentaire.

xy=0,999x \otimes y = 0{,}999

Bilan : Le résultat mathématique devrait être 13×3=1\frac{1}{3} \times 3 = 1, mais l'arithmétique flottante donne 0,9990{,}999. L'erreur provient de la représentation initiale de 13\frac{1}{3}, 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 ε2\frac{\varepsilon}{2})
  • L'erreur d'entrée (ici, 13\frac{1}{3} n'est pas représentable exactement)

L'erreur totale peut excéder ε2\frac{\varepsilon}{2} à 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 :

absorption.pypython
# 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 37800,3213780 \ominus 0{,}321 dans un système (b=10,s=3)(b=10, s=3).

Étape 1 : Représenter les opérandes en notation normalisée

x=fl(3780)=3,78×103x = \text{fl}(3780) = 3{,}78 \times 10^3
y=fl(0,321)=3,21×101y = \text{fl}(0{,}321) = 3{,}21 \times 10^{-1}

Étape 2 : Aligner les exposants

Pour soustraire, on exprime yy avec l'exposant de xx :

y=3,21×101=0,000321×103y = 3{,}21 \times 10^{-1} = 0{,}000321 \times 10^3

Étape 3 : Effectuer la soustraction exacte

xy=3,780,000321=3,779679x - y = 3{,}78 - 0{,}000321 = 3{,}779679

Résultat exact : 3,779679×103=3779,6793{,}779679 \times 10^3 = 3779{,}679

Étape 4 : Arrondir à s=3s=3 chiffres

Par troncature :

tron(3,779679×103,3)=3,77×103=3770\text{tron}(3{,}779679 \times 10^3, 3) = 3{,}77 \times 10^3 = 3770

Par arrondissement :

arrondi(3,779679×103,3)=3,78×103=3780\text{arrondi}(3{,}779679 \times 10^3, 3) = 3{,}78 \times 10^3 = 3780

Observation : Par arrondissement, le résultat est identique à l'opérande initial ! Le petit nombre y=0,321y = 0{,}321 a été complètement « absorbé ». C'est un cas typique où xy=xx \ominus y = x alors que xyxx - y \neq x.

Perte d'associativité

En mathématiques, l'addition est associative :

(a+b)+c=a+(b+c)(a + b) + c = a + (b + c)

En arithmétique flottante, cette propriété n'est plus garantie.

associativite.pypython
# 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, a+b=0a + b = 0 exactement, puis 0+c=10 + c = 1.

Dans le second cas, b+cbb + c \approx b (le 1 est absorbé), puis a+b=0a + b = 0.

🚨

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 d'associativité de la multiplication (dépassement intermédiaire)

La multiplication aussi peut perdre son associativité dans des cas extrêmes :

associativite_multiplication.pypython
# 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 toujours commutative en IEEE 754,
# mais l'ordre des produits 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.

fl(fl(fl(a+b)+c)+d)a+b+c+d\text{fl}(\text{fl}(\text{fl}(a + b) + c) + d) \neq a + b + c + d

Résumé des pièges courants

PiègeCauseConséquence
AbsorptionAddition de nombres d'ordres très différentsLe petit nombre est « ignoré »
Perte d'associativitéOrdres de grandeur variésRésultat dépend de l'ordre des opérations
Accumulation d'erreursLongues chaînes de calculsErreur finale peut être très grande
Dépassement/soupassementRésultats hors plageInf, 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 :

Troncature : xtron(x,s)x<b1s=ε\text{Troncature : } \left| \frac{x - \text{tron}(x, s)}{x} \right| < b^{1-s} = \varepsilon
Arrondissement : xarrondi(x,s)x12b1s=ε2\text{Arrondissement : } \left| \frac{x - \text{arrondi}(x, s)}{x} \right| \leq \frac{1}{2} b^{1-s} = \frac{\varepsilon}{2}

Modèle standard pour les opérations (IEEE 754) :

fl(xy)=(xy)(1+δ)avec δε2\text{fl}(x \circ y) = (x \circ y)(1 + \delta) \quad \text{avec } |\delta| \leq \frac{\varepsilon}{2}

Points essentiels

  • La troncature est biaisée (vers zéro), l'arrondissement minimise l'erreur moyenne
  • Chaque opération flottante (,,,\oplus, \ominus, \otimes, \oslash) introduit une erreur relative bornée par ε2\frac{\varepsilon}{2}
  • 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 : a=1020a = 10^{20}, b=1020b = -10^{20}, c=1c = 1.

  1. Calculez (a+b)+c(a + b) + c à la main en arithmétique exacte.
  2. Calculez a+(b+c)a + (b + c) à la main en arithmétique exacte.
  3. Expliquez pourquoi Python donne des résultats différents pour ces deux expressions.
  4. 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 b=10b = 10 et s=4s = 4 chiffres de mantisse, calculez les représentations par troncature et par arrondissement des nombres suivants :

  1. x=12,3456x = 12{,}3456
  2. x=0,0098765x = 0{,}0098765
  3. x=98765,4321x = 98765{,}4321

Pour chaque cas :

  • Normalisez le nombre sous la forme d1,d2d3×10ed_1{,}d_2d_3\cdots \times 10^e
  • Calculez tron(x,s)\text{tron}(x, s) et arrondi(x,s)\text{arrondi}(x, s)
  • Vérifiez que les erreurs relatives respectent les bornes ε\varepsilon et ε2\frac{\varepsilon}{2}
💡

Indice

Rappel des bornes pour b=10,s=4b=10, s=4 : ε=1014=103=0,1%\varepsilon = 10^{1-4} = 10^{-3} = 0{,}1\%.

Exercice 3 : Absorption en pratique

Écrivez un programme Python qui :

  1. Calcule la somme S=1+1016+1016+S = 1 + 10^{-16} + 10^{-16} + \cdots (un million de termes 101610^{-16})
  2. Compare le résultat avec la valeur théorique 1+10101 + 10^{-10}
  3. Propose une méthode pour obtenir un résultat plus précis

Exercice 4 : Multiplication et précision

Dans un système (b=10,s=3)(b=10, s=3), calculez pas à pas le produit 2,34×5,672{,}34 \times 5{,}67.

  1. Représentez chaque opérande en notation flottante normalisée.
  2. Effectuez la multiplication des mantisses.
  3. Additionnez les exposants.
  4. Renormalisez si nécessaire.
  5. Arrondissez à 3 chiffres.
  6. Comparez avec le résultat exact.