Vous êtes sur une version archivée de lyceum.fr de l'année 2023/2024. Revenir au présent.

Chapitre 3: Représentation des nombres à virgule

Contenus Capacités attendues Commentaires
Représentation approximative des nombres réels: notion de nombre flottant Représentation approximative des nombres réels: notion de nombre flottant 0.2 + 0.1 n’est pas égal à 0.3. Il faut éviter de tester l’égalité de deux flottants. Aucune connaissance précise de la norme IEEE-754 n’est exigible.

Nous avons appris à encoder des nombres entiers naturels, et relatifs, et nous avons vu que les limites physiques des machines imposaient des limites sur l’étendue des valeurs. Maintenant que nous allons tenter de coder les réels, les limites de notre machine vont encore entraîner des limites sur l’étendue des valeurs, mais également sur la précision des valeurs.

Pour encoder un nombre flottant on
utilise 1 bit de signe f bits pour la mantisse et e bits pour l'exposant.
Pour encoder un nombre flottant on utilise 1 bit de signe f bits pour la mantisse et e bits pour l'exposant.
©  CC BY-SA 3.0 via Wikimedia Commons

1 Virgule fixe et virgule flottante

Il existe deux façons de coder les nombres à virgule:

  • Le codage en virgule fixe qui consiste à garder un nombre fixe de chiffes après la virgule.

Par exemple sur un octet, on peut utiliser 4 bits pour la partie entière et 4 bits pour la partie décimale.

Ainsi, 0101 1011 a pour valeur:

2 2 + 2 0 + 2 1 + 2 2 + 2 3 = 4 + 1 + 0.5 + 0.25 + 0.125 = 5 , 825 2^2 + 2^0 + 2^{-1} + 2^{-2} + 2^{-3} = 4 + 1 + 0.5 + 0.25 + 0.125 = 5,825

  • Dans le codage en virgule flottante, on garde un nombre fixe de chiffres significatifs et on réserve l’autre partie du codage à l’exposant. C’est une méthode semblable à la notation scientifique utilisée en physique, mais avec des puissances de 2.

± m × 2 n avec m [ 1 ; 2 [ \pm m \times 2^{n} \text{ avec } m \in [1; 2[

C’est cette deuxième méthode qui est utilisée dans les ordinateurs et smartphones et que nous allons étudier cette année.

2 Principe du codage en virgule flottante

On représente un nombre à virgule flottante sous la forme:

s m 2 n s\ m \cdot 2^n

Pour encoder un nombre flottant on
utilise 1 bit de signe f bits pour la mantisse et e bits pour l'exposant.
Pour encoder un nombre flottant on utilise 1 bit de signe f bits pour la mantisse et e bits pour l'exposant.
©  CC BY-SA 3.0 via Wikimedia Commons

Supposons un nombre flottant codé sur un octet utilisant 1 bit de signe, 3 bits pour l’exposant et 4 bits pour la mantisse: 1 100 1011

  • s s est le signe représenté par le bit de poids fort:

    • s = 0 s=0 : signe + +
    • s = 1 s=1 : signe -

    s = 1 s=1 Notre codage représente donc un nombre négatif.

  • n n est l’exposant représenté par un entier relatif décalé et non en complément à deux(ceci afin de faciliter la comparaison des exposants).

    Ce décalage est de 2 e 1 1 2^{e-1} - 1 (e représente le nombre de bits utilisé pour coder l’exposant)

    L’exposant a pour valeur 100 codé sur 3 bits, il doit être décalé de 2 2 1 = 3 2^{2} - 1 = 3 . Ainsi, puisque 100 2 = 4 10 100_2 = 4_{10} , l’exposant 100 correspond à un exposant de 4-3=1.

  • m m est la mantisse qui est un nombre binaire à virgule compris entre 1 inclus et 2 exclus. Le seul chiffre avant la virgule étant toujours 1, il n’est pas représenté(on le dit implicite), et le codage binaire de la mantisse représente donc uniquement les chiffres après la virgule qui sont despuissances négatives de 2: de gauche à droite, un demi, un quart, un huitème, un seizième…

Dans notre exemple, la mantisse est: 1011, elle représentera le nombre:

m = 1 + 1 2 + 1 2 3 + 1 2 4 = 1 + 0 , 5 + 0 , 125 + 0 , 0625 = 1 , 6875 m = 1 + \frac{1}{2} + \frac{1}{2^3}+ \frac{1}{2^4} = 1+0,5+0,125+0,0625 = 1,6875

Le code 1 101 1011 sur un octet utilisant 1 bit de signe, 3 bits pour l’exposant et 4 bits pour la mantisse représente donc:

1 , 6875 2 1 = 3 , 375 - 1,6875 \cdot 2^{1}= -3,375

Calculer la valeur représentée par le codage suivant sur 16 bits

Les 16 bits sont répartis en 7 bits de mantisse, 8 bits d'exposant et 1 bit de signe.
Les 16 bits sont répartis en 7 bits de mantisse, 8 bits d'exposant et 1 bit de signe.
©  CC BY-SA 4.0 via Wikimedia Commons

3 La norme IEEE 754

L’IEEE 754 est une norme pour la représentation des nombres à virgule flottante en binaire. Elle est la norme la plus employée actuellement pour le calcul des nombres à virgule flottante dans le domaine informatique. Source Wikipédia

Cette norme définit notamment 2 formats pour représenter des nombres à virgule flottante:

simple précision (32 bits : 1 bit de signe, 8 bits d’exposant (-126 à 127), 23 bits de mantisse),

double précision (64 bits : 1 bit de signe, 11 bits d’exposant (-1022 à 1023), 52 bits de mantisse).

Norme IEEE 754 de codage simple précision sur 32 bits.
Norme IEEE 754 de codage simple précision sur 32 bits.
©  CC BY-SA 3.0 via Wikimedia Commons

Norme IEEE 754 de codage simple précision sur 64 bits.
Norme IEEE 754 de codage simple précision sur 64 bits.
©  CC BY-SA 3.0 via Wikimedia Commons

  • en simple précision: ici
  • en double précision: ici

Comparer la précision obtenue dans les deux cas.

La norme donne une signification particulière au plus petit et au plus grand exposant pour définir certaines valeurs spéciales.

  • le zéro positif: +0 = 0 00000000000 0000000000000000000000000000000000000000000000000000,
  • le zéro négatif: -0 = 1 00000000000 0000000000000000000000000000000000000000000000000000,
  • l’infini positif: +∞ = 0 11111111111 0000000000000000000000000000000000000000000000000000,
  • l’infini négatif: +∞ = 1 11111111111 0000000000000000000000000000000000000000000000000000,
  • Not a Number …

Article Wikipédia en anglais

4 Tests d’égalité sur les flottants

Si on effectue le calcul 0.2 + 0.1 0.2 +0.1 en Python, on obtient:

>>> 0.2 + 0.1
0.30000000000000004

Et contre toute attente, certains tests que l’on aurait cru positifs renvoient des valeurs négatives(ce que l’on appelle un faux négatif):

>>> 0.2 + 0.1 == 0.3
False

Ainsi un calcul avec des nombres à virgule ne peut-être qu’approximatif. Cependant, plus on augmente la taille du registre du processeur et plus nous pourrons représenter de valeurs, et plus nos calculs gagneront en précision.

Comme nous sommes limités sur la précision des flottants, on transforme les tests d’égalités en tests d’inégalités à une précision donnée.

Ainsi:

>>> 0.2 + 0.1 == 0.3
False

Par contre, en utilisant une précision du millionième:

>>> import math # pour utiliser la fonction valeur absolue  fabs()
>>> precision = 1E-6
>>> math.fabs((0.2 + 0.1) - 0.3)  < precision
True

D’ailleurs la bibliothèque math de Python inclut à cet effet la fonction math.isclose().

>>> from math import isclose
>>> isclose(0.2 + 0.1, 0.3)
True