La représentation binaire des réels

Introduction à la norme IEEE 754

Cette page se veut une ressource pour élèves de première générale, cours de NSI (Numérique et Sciences Informatiques). Elle apporte une réponse aux questions « comment sont encodés les nombres réels non entiers et pourquoi ? » en restant à un niveau d’initiation. En particulier, la norme IEEE 754 n’est pas détaillée, conformément au programme.

Un nombre réel non entier ne peut pas être encodé tel quel, ne serait-ce que parce qu’il peut s’écrire avec un nombre infini de décimales. Il faut nécessairement employer une approximation.

Le réel approché est appelé flottant. Voyons par quel mécanisme bizarre il est encodé pour tenter de résister aux plus terribles calculs.

 

Écriture scientifique

Il serait tentant d’utiliser l’écriture scientifique, enseignée dès le collège. Tout nombre décimal peut s’écrire avec un signe, un nombre compris dans l’intervalle \(]1\, ; 10]\) (la mantisse ou significande) et une puissance entière de 10, positive ou négative (l’exposant).

Exemple : \(1 234,5 = +1,2345 \times 10^3.\)

Hélas, cette forme est mal adaptée à certaines opérations informatiques. Elle ne permet pas non plus de représenter l’infini ou de retourner un message d’erreur.

 

La norme IEEE 754

C’est pourquoi la plupart des processeurs et des langages de programmation s’appuient sur un système différent, la norme IEEE 754.

Créée en 1985, elle existe principalement en simple précision (32 bits, soit 4 octets, que nous détaillerons ci-dessous) et en double précision (64 bits).

L’encodage ne repose pas sur les puissances de 10 mais sur celles de 2. Comment les 32 bits de la simple précision se décomposent-ils ?

  • Le premier est celui du signe : 0 pour positif et 1 pour négatif (comme pour l’encodage des entiers relatifs).

  • Les huit suivants stockent l’exposant, c’est-à-dire la puissance de 2. Comme il n’y a pas de place pour le signe, l’astuce est de décaler la valeur de l’exposant. Étant donné que huit bits permettent d’encoder 256 nombres entiers positifs (entre 0 et 255), les exposants peuvent théoriquement se trouver dans l’intervalle \([-127\, ; 128].\) Nous verrons plus loin que ce n’est pas vraiment le cas. Retenez que pour passer du nombre réel à sa version encodée, il y a un décalage de 127 (ce nombre est appelé le biais). L’exposant stocké en binaire est donc égal à \(2^{\rm{exposant}-127}\) en base 10. Par exemple, 64 est égal à \(2^6\) donc l’exposant vaut \(6 + 127 = 133\) ce qui en base 2 s’écrit 10000101.

  • Les 23 bits suivants stockent la « mantisse ». Elle est comprise dans l’intervalle \([1\, ; 2[.\) Il s’agit de la partie après la virgule que l’on appelle fraction. Attention, nous ne parlons pas de la partie décimale du nombre en base 10 mais bien de celle qui doit être multipliée à une puissance de 2. En base 10, elle a pour valeur 1 plus la somme du premier bit multiplié par \(2^{-1},\) du deuxième multiplié par \(2^{-2}\) et ainsi de suite jusqu’à \(2^{-23}.\)

Exemple : 0 10000101 00100010010000000000000 (nous avons placé des espaces dans le seul but de clarifier la lecture).

Pour faciliter la compréhension des exemples, voici les premières puissances positives de 2 :

\(2^0\) 1
\(2^1\) 2
\(2^2\) 4
\(2^3\) 8
\(2^4\) 16
\(2^5\) 32
\(2^6\) 64
\(2^7\) 128
\(2^8\) 256

Quant aux puissances négatives…

\(2^{-1}\) 0,5
\(2^{-2}\) 0,25
\(2^{-3}\) 0,125
\(2^{-4}\) 0,0625
\(2^{-5}\) 0,03125
\(2^{-6}\) 0,015625
\(2^{-7}\) 0,0078125
\(2^{-8}\) 0,00390625
  • Le premier bit est 0. Nous avons affaire à un nombre positif.

  • En traduisant 10000101 depuis la base 2 vers la base 10, l’exposant vaut \(2^7 + 2^2 + 2^0\) \(=\) \(133\) auquel on retranche 127. Il est donc égal à 6.

  • La mantisse est égale à \(1 + 2^{-3} + 2^{-7} + 2^{-10},\) soit 1,1337890625. Multiplions ce nombre par \(2^{6}.\) On obtient 72,5625.

Faisons à présent le chemin inverse. Comment encoder 72,5625 ?

  • Le premier bit est 0.

  • 72,5625 est compris entre \(2^6\) et \(2^7\) (entre 64 et 128). On prend la plus petite puissance et on lui ajoute le biais de 127. L’exposant est donc égal à \(6 + 127 = 133.\) En binaire : 10000101.

  • Pour trouver la fraction, on écrit en binaire 72,5605. C’est 1001000,1001. On déplace la virgule après le premier 1. Donc \(1,0010001001 \times 2^6.\) On ne prend que la partie située à droite de la virgule, soit 0010001001, auquel on ajoute treize zéros pour compléter les 23 bits. Nous retrouvons bien la mantisse de l’énoncé.

Un site pour les conversions :

https://binaryconvert.com/convert_float.html

Dans la mesure où la mantisse ne peut être nulle et l’exposant non plus puisque \(2^0 = 1,\) le zéro ne peut pas être encodé. Pour pallier ce détail fâcheux, on lui réserve l’exposant -127 (après décalage, donc 00000000) avec une mantisse nulle elle aussi. Le signe peut être positif ou négatif.

L’exposant 128, donc 255 avant décalage, indique l’infini lorsqu’il est couplé à une mantisse nulle et une valeur invalide lorsqu’il est couplé à une matisse non nulle.

 

Approximations

Tous les réels ne peuvent pas être représentés avec un nombre fini de bits, même s’ils ont un nombre fini de décimales.

Prenons l’exemple de 0,1 (en base 10).

Son signe est positif, le flottant commence par zéro.

0,1 est compris entre \(2^{-4}\) et \(2^{-3}.\) Donc l’exposant s’élève à \(-4 + 127 = 123.\) Comme \(123\) \(=\) \(64 + 32 + 16 + 8+ 2 + 1\) sa forme binaire est 01111011. Jusque-là, aucun problème.

Reste à trouver la partie fractionnaire. Écrivons 0,1 en base 2.

\(0,1 \times 2 = 0,2 = 0 + 0,2\)
\(0,2 \times 2 = 0,4 = 0 + 0,4\)
\(0,4 \times 2 = 0,8 = 0 + 0,8\)
\(0,8 \times 2 = 1,6 = 1 + 0,6\)
\(0,6 \times 2 = 1,2 = 1 + 0,2\)
\(0,2 \times 2 = 0,4 = 0 + 0,4\)

Et là nous constatons avec tristesse que nous répéterons indéfiniment la même séquence de quatre chiffres (0011). Il n’est donc pas possible d’encoder la valeur exacte de 0,1.

Conséquences : il ne faut jamais tester une égalité de deux flottants, faire très attention aux arrondis qui peuvent se cumuler dans des calculs successifs et comprendre que les propriétés d’associativité et de distributivité ne sont pas nécessairement vérifiées quand elles devraient l’être. Voir le troisième exercice d'encodage des nombres.

 

débat