Représentation en virgule flottante
Dans la leçon précédente, nous avons identifié les erreurs d'arrondi comme une source fondamentale d'imprécision. Ces erreurs découlent directement de la façon dont les ordinateurs représentent les nombres. Comprendre cette représentation est essentiel pour anticiper et contrôler le comportement des algorithmes numériques.
Le problème fondamental
L'ensemble des nombres réels possède deux propriétés qui le rendent impossible à représenter exactement dans un ordinateur : il est infini (il contient une infinité de nombres) et il est continu (entre deux nombres quelconques, il en existe toujours un autre).
Un ordinateur, en revanche, dispose d'une mémoire finie. Il ne peut stocker qu'un nombre fini de valeurs distinctes. Chaque nombre réel doit donc être approximé par l'un des nombres représentables dans la machine.
La question devient alors : comment choisir intelligemment quels nombres seront représentables ?
La notation en virgule flottante
La solution adoptée universellement est la notation en virgule flottante (ou notation flottante). Cette représentation s'inspire de la notation scientifique que vous connaissez déjà.
En notation scientifique, on écrit par exemple :
Cette notation sépare deux informations : les chiffres significatifs (la mantisse) et l'ordre de grandeur (l'exposant).
Définition formelle
En notation flottante, un nombre est représenté sous la forme :
où :
- est la base du système de numération
- est le nombre de chiffres de la mantisse (la précision)
- est l'exposant, avec
- sont les chiffres de la mantisse, avec
La notation désigne la représentation flottante du nombre .
La contrainte de normalisation
Pour garantir l'unicité de la représentation, on impose une contrainte supplémentaire :
Cette condition s'appelle la normalisation. Elle assure que le premier chiffre de la mantisse est toujours significatif.
Sans cette contrainte, un même nombre pourrait avoir plusieurs représentations. Par exemple, en base 10 avec 3 chiffres :
Avec la normalisation, seule la première forme est valide.
Le quadruplet caractéristique
Un système de numération en virgule flottante est entièrement défini par quatre paramètres : , soit la base, le nombre de chiffres de la mantisse, l'exposant minimal et l'exposant maximal.
Exemple : Un système miniature
Pour bien comprendre, construisons un système flottant minimal avec les paramètres suivants :
Ce système utilise la base 2 (binaire), une mantisse de 2 chiffres, et des exposants allant de -2 à 3.
Quels nombres sont représentables ?
Les nombres normalisés dans ce système ont la forme :
En base 2, la seule valeur non nulle pour est 1. Pour , nous avons le choix entre 0 et 1. Les mantisses possibles sont donc :
Pour chaque mantisse, nous avons 6 exposants possibles ().
Voici la liste complète des nombres positifs représentables :
| Mantisse | Exposant | Calcul | Valeur décimale |
|---|---|---|---|
Notre système miniature ne peut représenter que 12 nombres positifs distincts (plus leurs opposés négatifs et le zéro).
Visualisation sur la droite réelle
Si nous plaçons ces nombres sur une droite, nous observons un phénomène important :
Nombres positifs représentables :
0 0.125 0.25 0.5 1 2 4 6
| | | | | | | |
+------+------+------+------+------+------+------+-->
0.1875 0.375 0.75 1.5 3
Observation : les nombres sont plus serrés près de zéro
et plus espacés pour les grandes valeurs.Les nombres représentables ne sont pas uniformément distribués. Ils sont plus denses près de zéro et plus espacés pour les grandes valeurs. C'est une propriété fondamentale de la représentation en virgule flottante : la précision relative est à peu près constante, mais la précision absolue varie.
La droite des flottants
La représentation en virgule flottante divise la droite réelle en plusieurs zones distinctes.
Zone représentable
Les nombres dont la valeur absolue est comprise entre le plus petit nombre normalisé positif et le plus grand nombre représentable peuvent être approximés.
Dans notre système miniature :
- Plus petit positif normalisé :
- Plus grand positif :
Dépassement de capacité (overflow)
Lorsqu'un calcul produit un résultat dont la valeur absolue dépasse le plus grand nombre représentable, on parle de dépassement de capacité (en anglais, overflow).
Dans notre système, tout nombre supérieur à 6 (ou inférieur à -6) provoque un dépassement.
Soupassement de capacité (underflow)
Lorsqu'un résultat non nul est trop proche de zéro pour être représenté, on parle de soupassement de capacité (en anglais, underflow).
Dans notre système, tout nombre positif inférieur à (mais non nul) provoque un soupassement.
Conséquences pratiques
Le dépassement de capacité produit généralement une valeur spéciale notée « Inf » (infini). Le soupassement peut produire zéro ou une valeur dénormalisée, selon le système. Ces situations peuvent propager des erreurs catastrophiques dans un calcul.
Compter les nombres représentables
Combien de nombres distincts un système flottant peut-il représenter ?
Pour un système :
- Nombre de mantisses distinctes : (le premier chiffre a choix, les autres en ont )
- Nombre d'exposants :
- Avec les signes et le zéro :
Pour notre système miniature :
(12 positifs + 12 négatifs + le zéro)
La norme IEEE 754
Les ordinateurs modernes utilisent la norme IEEE 754, qui définit deux formats principaux. Cette norme est le standard universel utilisé par pratiquement tous les processeurs.
Structure générale d'un nombre flottant
Un nombre flottant est stocké en trois parties distinctes :
Prenons l'exemple de la simple précision (32 bits) pour tout expliquer :
| Partie | Nombre de bits | Rôle |
|---|---|---|
| Signe | 1 bit | 0 = positif, 1 = négatif |
| Exposant | 8 bits | Détermine l'ordre de grandeur |
| Mantisse | 23 bits | Stocke les chiffres significatifs |
Le problème des exposants négatifs
L'exposant doit pouvoir être positif ou négatif. Par exemple :
- → exposant positif (grand nombre)
- → exposant négatif (petit nombre)
Plutôt que d'utiliser un bit de signe pour l'exposant, la norme IEEE 754 utilise une astuce appelée exposant biaisé.
L'idée : On stocke la valeur où :
- est l'exposant réel (celui qu'on veut représenter)
- est la valeur stockée dans les 8 bits (toujours positive)
- Le biais vaut en simple précision
Pourquoi 127 ? Avec 8 bits, on peut stocker des valeurs de 0 à 255. En choisissant un biais de 127, on peut représenter des exposants réels allant de à :
| Valeur stockée (e) | Exposant réel (E = e − 127) | Remarque |
|---|---|---|
| 0 | — | Réservé (zéro et dénormalisés) |
| 1 | Plus petit exposant utilisable | |
| 127 | Exposant nul | |
| 254 | Plus grand exposant utilisable | |
| 255 | — | Réservé (infini et NaN) |
Les valeurs 0 et 255 sont réservées pour des cas spéciaux que nous verrons plus loin.
Le bit implicite : une astuce pour gagner de la précision
En notation scientifique normalisée en base 2, tout nombre s'écrit :
Le premier chiffre avant la virgule est toujours 1 (c'est la définition de la normalisation en binaire). Puisqu'il est toujours égal à 1, pourquoi le stocker ?
L'astuce IEEE 754 : On ne stocke pas ce 1. Il est « implicite ». Les 23 bits de mantisse stockent uniquement la partie après la virgule (appelée partie fractionnaire ).
Exemple concret : Représentons le nombre .
Étape 1 : Convertir en binaire.
Étape 2 : Normaliser (décaler la virgule pour avoir 1,xxx).
Étape 3 : Identifier les composantes.
- Signe : 0 (positif)
- Exposant réel : , donc valeur stockée :
- Partie fractionnaire : (le 1 avant la virgule n'est pas stocké)
Représentation sur 32 bits :
Formule de reconstruction d'un nombre
Pour reconstruire le nombre à partir de sa représentation, on utilise :
où est la valeur de la partie fractionnaire (entre 0 et presque 1).
Vérifions avec notre exemple () :
(Car )
Calcul du plus grand nombre représentable
Maintenant que nous comprenons la structure, trouvons le plus grand nombre possible.
Pour maximiser un nombre, il faut :
- Un signe positif (0)
- L'exposant le plus grand possible
- La mantisse la plus grande possible
Quel est l'exposant maximum ?
La valeur stockée va de 0 à 255, mais :
- est réservé pour le zéro et les nombres dénormalisés
- est réservé pour l'infini () et NaN
Donc l'exposant maximum utilisable est , ce qui donne :
Quelle est la mantisse maximum ?
La mantisse est maximale quand tous ses 23 bits sont à 1 :
Cette somme est une série géométrique. Calculons-la :
C'est la somme d'une suite géométrique de raison :
Avec le bit implicite (le 1 avant la virgule), la mantisse complète vaut :
Le plus grand nombre est donc :
Calculons numériquement :
Calcul du plus petit nombre positif normalisé
Pour minimiser un nombre positif, il faut :
- L'exposant le plus petit possible
- La mantisse la plus petite possible
Quel est l'exposant minimum ?
La plus petite valeur utilisable est (car est réservé) :
Quelle est la mantisse minimum ?
La mantisse est minimale quand tous ses bits sont à 0 :
Avec le bit implicite :
Le plus petit nombre positif normalisé est donc :
Représentation du zéro
En IEEE 754, le zéro est représenté par un exposant et une mantisse tous deux nuls :
- Exposant : (les 8 bits à 0)
- Mantisse : (les 23 bits à 0)
Zéros signés : IEEE 754 distingue et selon le bit de signe. Arithmétiquement, ils sont égaux ( retourne vrai), mais leur représentation binaire diffère. Cette distinction peut être utile pour préserver le signe lors d'un underflow vers zéro.
Nombres dénormalisés (sous-normaux)
Quand l'exposant est nul () mais la mantisse est non nulle (), on obtient un nombre dénormalisé. Dans ce cas, le bit implicite est 0 (au lieu de 1) et l'exposant est fixé à :
Ces nombres permettent un underflow graduel : ils comblent l'écart entre zéro et le plus petit nombre normalisé, évitant un saut brutal vers zéro.
Plus petit nombre positif dénormalisé
Le plus petit nombre positif représentable (dénormalisé) est :
Représentation de l'infini
L'infini est représenté avec un exposant maximal (tous les bits à 1) et une mantisse nulle :
- Exposant : (les 8 bits à 1)
- Mantisse :
Utilité : L'infini permet de représenter le résultat d'un overflow (dépassement de capacité) ou d'opérations comme . Les opérations arithmétiques avec l'infini sont bien définies : , , etc.
NaN (Not a Number)
NaN (Not a Number) représente le résultat d'opérations mathématiquement indéfinies. Il est encodé avec un exposant maximal et une mantisse non nulle :
- Exposant :
- Mantisse :
Opérations produisant NaN :
- pour
Propriété importante : NaN n'est égal à aucune valeur, y compris lui-même. Le test retourne vrai si et seulement si est NaN. C'est la méthode standard pour détecter un NaN.
Propagation des NaN
Toute opération arithmétique impliquant un NaN produit un NaN. Cela permet de détecter qu'une erreur s'est produite quelque part dans un calcul.
Récapitulatif des valeurs spéciales
| Type | Exposant e | Mantisse f | Valeur |
|---|---|---|---|
| Zéro | 0 | 0 | |
| Dénormalisé | 0 | ||
| Normalisé | 1 à 254 | quelconque | |
| Infini | 255 | 0 | |
| NaN | 255 | Not a Number |
Calcul de l'epsilon machine
L'epsilon machine (aussi appelé machine epsilon) caractérise la précision relative du système flottant. Sa définition exacte varie selon les auteurs, mais la définition la plus courante est :
Définition de l'epsilon machine
L'epsilon machine est l'écart entre 1 et le plus petit nombre flottant strictement supérieur à 1.
Calcul pour IEEE 754 simple précision :
Le nombre 1 s'écrit en IEEE 754 avec une mantisse de 23 bits (plus le bit implicite) :
Le nombre flottant immédiatement supérieur à 1 est celui où le bit le moins significatif de la mantisse passe de 0 à 1 :
L'écart entre ces deux nombres est :
Lien avec l'erreur d'arrondi :
Quand on arrondit un nombre réel au nombre flottant le plus proche, l'erreur maximale est la moitié de l'écart entre deux nombres flottants consécutifs. Autour de 1, cet écart est , donc l'erreur maximale est .
Plus généralement, pour tout nombre réel dans la plage normale :
La quantité est parfois appelée unit roundoff ou unité d'arrondi.
Attention aux conventions
Certains auteurs définissent directement comme la borne d'erreur relative (ce que nous appelons ). Vérifiez toujours la convention utilisée dans vos références !
Interprétation pratique : En simple précision, on a environ 7 chiffres décimaux de précision (car ).
Algorithme de calcul de l'epsilon machine :
L'algorithme suivant permet de calculer expérimentalement l'epsilon machine par recherche linéaire. Il retourne une valeur à un facteur 2 près de la valeur exacte :
epsilon = 1.0
while (1.0 + 0.5 * epsilon) != 1.0:
epsilon = 0.5 * epsilon
print(f"Epsilon machine ≈ {epsilon}")
# En double précision : ≈ 2.220446049250313e-16Pourquoi cet algorithme fonctionne ?
À chaque itération, on divise par 2. La boucle s'arrête quand est arrondi à exactement 1, c'est-à-dire quand est trop petit pour affecter la représentation de 1. À ce moment, est l'écart entre 1 et le nombre flottant suivant.
Récapitulatif : Simple précision (32 bits)
| Propriété | Formule | Valeur approximative |
|---|---|---|
| Plus grand nombre | ||
| Plus petit normalisé | ||
| Epsilon machine | ||
| Unité d'arrondi | ||
| Chiffres de précision | ≈ 7 chiffres décimaux |
Double précision (64 bits)
Le raisonnement est identique, avec des paramètres différents :
| Paramètre | Simple précision | Double précision |
|---|---|---|
| Bits pour l'exposant | 8 | 11 |
| Bits pour la mantisse | 23 | 52 |
| Biais | 127 | 1023 |
| Exposant max utilisable | 254 → E = 127 | 2046 → E = 1023 |
| Exposant min utilisable | 1 → E = -126 | 1 → E = -1022 |
| Propriété | Valeur | Approximation |
|---|---|---|
| Plus grand nombre | ||
| Plus petit normalisé | ||
| Epsilon machine | ||
| Unité d'arrondi | ||
| Chiffres de précision | ≈ 15-16 chiffres décimaux |
Python utilise la double précision
En Python, le type float est toujours en double précision (64 bits). C'est pourquoi vous avez environ 15 chiffres décimaux de précision. Pour utiliser la simple précision, il faut passer par NumPy (numpy.float32).
Valeurs spéciales
La norme IEEE 754 définit également des valeurs spéciales pour représenter les situations exceptionnelles :
| Valeur | Signification | Exemple de cause |
|---|---|---|
| et | Dépassement de capacité | |
| NaN (Not a Number) | Résultat indéfini | ou |
| Zéros signés (, ) | Soupassement avec signe |
import math
# Démonstration des valeurs spéciales
print("=== Valeurs spéciales IEEE 754 ===")
# Infini
print(f"1e308 * 10 = {1e308 * 10}") # inf
print(f"-1e308 * 10 = {-1e308 * 10}") # -inf
# NaN
print(f"0.0 / 0.0 = {0.0 / 0.0}") # nan (avec avertissement)
print(f"inf - inf = {float('inf') - float('inf')}") # nan
# Propriété étrange de NaN
nan = float('nan')
print(f"nan == nan : {nan == nan}") # False (!)Attention
NaN possède une propriété unique : il n'est égal à rien, pas même à lui-même. Le test retourne toujours . Utilisez la fonction pour détecter les NaN.
Démonstrations en Python
Observer les limites du système
import sys
# Informations sur les flottants en Python (double précision)
print("=== Caractéristiques des flottants ===")
print(f"Plus grand flottant : {sys.float_info.max:.6e}")
print(f"Plus petit positif : {sys.float_info.min:.6e}")
print(f"Epsilon machine : {sys.float_info.epsilon:.6e}")
print(f"Chiffres de précision : {sys.float_info.dig}")
# Démonstration du dépassement de capacité
print("\n=== Dépassement de capacité ===")
grand = 1e308
print(f"1e308 = {grand}")
print(f"1e308 * 10 = {grand * 10}") # Produit 'inf'
# Démonstration du soupassement
print("\n=== Soupassement de capacité ===")
petit = 1e-308
print(f"1e-308 = {petit}")
print(f"1e-308 / 1e20 = {petit / 1e20}") # Approche de zéroCalcul expérimental de l'epsilon
# Méthode 1 : Calcul itératif
eps = 1.0
while 1.0 + eps != 1.0:
eps_precedent = eps
eps = eps / 2.0
print(f"Epsilon calculé : {eps_precedent}")
# Méthode 2 : Valeur système
import sys
print(f"Epsilon système : {sys.float_info.epsilon}")
# Méthode 3 : Avec NumPy
import numpy as np
print(f"Epsilon float32 : {np.finfo(np.float32).eps}")
print(f"Epsilon float64 : {np.finfo(np.float64).eps}")Ce qu'il faut retenir
La représentation en virgule flottante est un compromis entre la plage de valeurs représentables et la précision. Le système définit complètement les nombres représentables dans une machine.
Les points essentiels sont :
- Les nombres flottants forment un ensemble fini et discret
- Ils ne sont pas uniformément distribués : plus denses près de zéro
- Le dépassement et le soupassement de capacité sont des situations à surveiller
- La normalisation garantit l'unicité de la représentation
- L'epsilon machine quantifie la précision relative du système
- La norme IEEE 754 définit les formats standard (32 et 64 bits)
Dans la prochaine leçon, nous étudierons ce qui se passe lorsqu'on effectue des opérations arithmétiques sur ces nombres : comment les erreurs d'arrondi apparaissent concrètement lors des additions, soustractions, multiplications et divisions.
Exercices de réflexion
Exercice 1 : Construire un système flottant
Considérons un système flottant en base 10 avec les paramètres .
- Listez toutes les mantisses normalisées possibles.
- Combien de nombres positifs distincts ce système peut-il représenter ?
- Quel est le plus petit nombre positif représentable ? Le plus grand ?
- Le nombre est-il représentable exactement dans ce système ?
Indice
En base 10 avec normalisation, le premier chiffre peut prendre les valeurs 1, 2, 3, ..., 9. Le second chiffre peut prendre les valeurs 0, 1, 2, ..., 9.
Exercice 2 : Identifier les zones problématiques
Dans le système miniature étudié dans cette leçon :
- Que se passe-t-il si on tente de représenter le nombre ?
- Que se passe-t-il si on tente de représenter le nombre ?
- Entre quels nombres représentables consécutifs se trouve ?
- Quelle serait l'erreur d'arrondi si on approximait par le nombre représentable le plus proche ?
Exercice 3 : Réflexion sur la densité
Observez la distribution des nombres représentables dans notre système miniature :
0.125, 0.1875, 0.25, 0.375, 0.5, 0.75, 1, 1.5, 2, 3, 4, 6- Calculez l'écart entre deux nombres consécutifs pour l'intervalle .
- Calculez l'écart entre deux nombres consécutifs pour l'intervalle .
- Comment l'écart entre nombres consécutifs évolue-t-il lorsque les nombres grandissent ?
- Expliquez pourquoi cette propriété est une conséquence directe de la représentation en virgule flottante.
Point clé à retenir
Cette variation de la densité explique pourquoi l'erreur absolue d'arrondi augmente avec la magnitude des nombres, tandis que l'erreur relative reste à peu près constante. C'est une caractéristique fondamentale de l'arithmétique flottante.
Exercice 4 : Explorer les limites en Python
Écrivez un programme Python qui :
- Affiche les valeurs de
sys.float_info.max,sys.float_info.minetsys.float_info.epsilon. - Vérifie expérimentalement que
1.0 + epsilon/2 == 1.0est vrai mais1.0 + epsilon == 1.0est faux. - Trouve le plus petit entier tel que en double précision.