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 :

MantisseExposantCalculValeur 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 :

text
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 :

PartieNombre de bitsRôle
Signe1 bit0 = positif, 1 = négatif
Exposant8 bitsDétermine l'ordre de grandeur
Mantisse23 bitsStocke 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
0Réservé (zéro et dénormalisés)
1Plus petit exposant utilisable
127Exposant nul
254Plus grand exposant utilisable
255Ré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 :

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 :

  1. Un signe positif (0)
  2. L'exposant le plus grand possible
  3. 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 :

  1. L'exposant le plus petit possible
  2. 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

TypeExposant eMantisse fValeur
Zéro00
Dénormalisé0
Normalisé1 à 254quelconque
Infini2550
NaN255Not 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 :

calcul_epsilon.pypython
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-16

Pourquoi 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éFormuleValeur 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ètreSimple précisionDouble précision
Bits pour l'exposant811
Bits pour la mantisse2352
Biais1271023
Exposant max utilisable254 → E = 1272046 → E = 1023
Exposant min utilisable1 → E = -1261 → E = -1022
PropriétéValeurApproximation
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 :

ValeurSignificationExemple de cause
et Dépassement de capacité
NaN (Not a Number)Résultat indéfini ou
Zéros signés (, )Soupassement avec signe
valeurs_speciales.pypython
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

limites_flottants.pypython
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éro

Calcul expérimental de l'epsilon

epsilon_machine.pypython
# 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 .

  1. Listez toutes les mantisses normalisées possibles.
  2. Combien de nombres positifs distincts ce système peut-il représenter ?
  3. Quel est le plus petit nombre positif représentable ? Le plus grand ?
  4. 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 :

  1. Que se passe-t-il si on tente de représenter le nombre ?
  2. Que se passe-t-il si on tente de représenter le nombre ?
  3. Entre quels nombres représentables consécutifs se trouve ?
  4. 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 :

text
0.125, 0.1875, 0.25, 0.375, 0.5, 0.75, 1, 1.5, 2, 3, 4, 6
  1. Calculez l'écart entre deux nombres consécutifs pour l'intervalle .
  2. Calculez l'écart entre deux nombres consécutifs pour l'intervalle .
  3. Comment l'écart entre nombres consécutifs évolue-t-il lorsque les nombres grandissent ?
  4. 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 :

  1. Affiche les valeurs de sys.float_info.max, sys.float_info.min et sys.float_info.epsilon.
  2. Vérifie expérimentalement que 1.0 + epsilon/2 == 1.0 est vrai mais 1.0 + epsilon == 1.0 est faux.
  3. Trouve le plus petit entier tel que en double précision.