Aller au contenu

1NSI : IEEE-754. Représentation Approximative des nombres Réels⚓︎

Contenus Capacités
Attendues
Commentaires
Représentation
approximative des
nombres réels : notion
de nombre flottant
Calculer sur quelques
exemples la représentation de
nombres réels : 0.1, 0.25 ou
1/3.
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.

Introduction⚓︎

L'encodage des nombres flottants est inspiré de l'écriture scientifique des nombres en base \(2\) : si l'écriture scientifique admet trop de chiffres après la virgule, alors on ajoute une troncature. La norme \(IEEE-754\) (Institute of Electrical and Electronics Engineers) sur l'arithmétique (des nombres) à virgule flottante / des nombres flottants, a été mise au point par l'IEEE en \(1985\) mais elle a été réactualisée en \(2008\) et \(2019\). Les détails précis de cette norme sont HORS-PROGRAMME, bien que certaines écritures simples puissent être demandés.

La norme définit des formats de représentation des nombres à virgule flottante / flottants :

  • signe \(s\)
  • exposant \(n\) (codé sur \(N\) bits)
  • mantisse \(f\)
  • nombres normalisés (nombres loin de \(0\))
  • nombres dénormalisés (nombres proches de \(0\))

Elle définit aussi des valeurs spéciales :

  • Zéros (\(\pm 0\))
  • Infinis (\(\pm \infty\))
  • NaN - Not a Number

Ainsi que des opérations, modes d'arrondis et exceptions :

  • des Opérations arithmétiques sur les nombres flottants
  • \(5\) modes d'arrondis
  • \(5\) exceptions (Opération Invalide, Division par Zéro, Overflow - résultat trop large, Underflow - résultat trop petit, Inexact - le résultat exact n'est pas représentable exactement), qui prennent en compte les conditions dans lesquelles une exception se produit, et ce qui doit se passer dans ce cas.

Principes Généraux Norme IEEE-754⚓︎

Présentation⚓︎

La norme \(IEEE-754\) propose de stocker en machine une approximation d'un nombre réel \(x\), en suivant le procédé suivant :

Pour commencer, le nombre réel \(x\) permet la détermination de l'unique triplet \((s,n,f)\) des trois nombres définis par la Notation Binaire Scientifique. Les nombres \(s, n\) et \(f\) sont tous les \(3\) écrits en binaire, consécutivement dans cet ordre, de gauche à droite :

  • \(s\) est un bit de signe
  • Ensuite, l'exposant \(n\) est décalé (ou biaisé) d'une certaine quantité \(d=2^{N-1}-1\)\(N\) désigne le nombre total de bits (décrits par la norme) utilisés pour représenter l'exposant \(n\), càd que le "nombre binaire \(IEEE-754\)" qui sera finalement/concrètement stocké en machine est \((s,n+d,f)\). Mais pourquoi me direz-vous? 🤔 La représentation habituelle des nombres signés (complément à \(2\)) rendrait la comparaison entre les nombres flottants un peu plus difficile. C'est pour régler ce problème que l'on utilise un exposant décalé / biaisé : cela permet de le stocker sous forme d'un nombre non signé (positif) dont les comparaisons sont plus simples.
  • Enfin, La partie fractionnaire \(f\) est éventuellement tronquée si elle est trop longue (c'est ici que s'impose la notion d'approximation du nombre) : On stockera donc un flottant qui sera donc une approximation du réel \(x\)

En pratique, la norme \(IEEE-754\) fait la différence (entre autres..) entre une représentation binaire :

  • Sur \(32\) bits / norme binary32 / en Simple Précision
  • Sur \(64\) bits / norme binary64 / en Double Précision

Nombres Normalisés vs Dénormalisés⚓︎

Le bit de poids fort de la mantisse \(m\) dépend de la valeur de l'exposant biaisé \(n+d\) :

  • Si l'exposant biaisé \(n+d \ne 0\) (pas tous les bits à \(0\)) et \(n+d \ne 2^{N}-1\) (pas tous les bits à \(1\)), alors le bit de poids fort de la mantisse \(m\) vaut \(1\), càd \(m=1+f\), et le nombre est dit normalisé. En pratique, ces nombres permettent une représentation des nombres flottants loin de \(0\). Remarquer qu'il existe :
    • un plus petit nombre positif normalisé (\(\approx 10^{-45}\) sur \(32\) bits, correspondant à l'exposant le plus petit qui soit représentable), et
    • un plus grand nombre positif normalisé (\(\approx 10^{31}\) sur \(32\) bits, correspondant à l'exposant le plus grand qui soit représentable).
  • Si l'exposant biaisé \(n+d=0\) (tous les bits à \(0\)), alors le bit de poids fort de la mantisse \(m\) vaut \(0\), càd \(m=0+f\), et le nombre est dit dénormalisé. En pratique, ces nombres permettent une (meilleure) représentation des nombres flottants très proches de \(0\) (càd entre \(0\) et le plus petit nombre normalisé positif).

Nombres Dénormalisés vs Normalisés

Code couleur : nombres dénormalisés, nombres normalisés

Cas Particuliers : \(\pm 0\), \(\pm \infty\), NaN⚓︎

Enfin, il y a \(3\) cas particuliers (ni nombres normalisés, ni nombres dénormalisés) :

  • \((s,n+d,f) = (s,0,0)\) représente \(\pm 0\) (selon le bit de signe)
  • \((s,n+d,f) = (s,2^{N}-1,0)\) représente \(\pm \infty\) (selon le bit de signe)
  • \((s,n+d,f) = (s,2^{N}-1,f)\) avec \(f\neq 0\) représente NaN - Not A Number 🇬🇧 / pas un nombre 🇫🇷. Les NaNs peuvent avoir des bits de signe \(s\), et une mantisse \(f\) (\(\ne 0\)), mais \(s\) et \(f\) n'admettent pas d'interprétations particulières. Il existe deux types de NaN :
    • Les NaN silencieux / qNaN - quiet NaN
    • Les NaN avec signalisation/avertissement / sNaN - signaling NaN. Ces sNaN servent à activer l'une des \(5\) exceptions existantes (Opération Invalide, Division par Zéo, Overflow - résultat trop large, Underflow - résultat trop petit, Inexact - le résultat exact n'est pas représentable exactement), et pour la correction d'erreurs.

Résumé⚓︎

Nous pouvons résumer les situations possibles dans le tableau suivant :

Type Exposant biaisé
\(n+d\)
Mantisse
\(f\)
\(\pm 0\) \(0\) \(f=0\)
Nombres dénormalisés \(0\) \(m=0+f\)
\(f \ne 0\)
Nombres normalisés \(1\) à \(2^{N}-2\) \(m=1+f\)
\(f\) quelconque
\(\pm \infty\) \(2^{N}-1\) \(f=0\)
NaNs \(2^{N}-1\) \(f \ne 0\)

⚠ En première approche, et en pratique, nous utiliserons principalement les nombres normalisés (compris entre \(\approx 10^{-45}\) et \(\approx 10^{31}\))

Sur \(32\) bits / binary\(32\) / Simple Précision⚓︎

Encodage 1+8+23⚓︎

La représentation \(IEEE-754\) des nombres flottants sur \(32\) bits, appelée simple précision, ou binary32 se décompose en un triplet \((s,n,f)\) issu initialement de la Notation Binaire Scientifique, mais avec les adaptations/précisions suivantes :

Pour 32 Bits

\(1+8+23=32\)

  • \(s\) est (stocké sur) \(1\) bit de signe :
    • \(s=0\) si \(x>0\) (car \((-1)^0=+1\)), ou bien
    • \(s=1\) si \(x<0\) (car \((-1)^1=-1\))
  • l'exposant \(n\) est stocké sur \(N=8\) bits :

    • Pour commencer, dans la norme \(IEEE-754\), les \(N=8\) bits de l'exposant entier \(n\) (à priori signé) ne sont pas utilisés pour stocker directement l'exposant \(n\) issu de la Notation Binaire Scientifique, mais plutôt un exposant décalé/biaisé \(n+d\) d'une quantité/décalage \(d = 2^{N-1}-1= 2^7-1 = 127\) (de sorte qu'il devienne un entier non signé).
    • Ensuite, La norme \(IEEE-754\) définit le stockage des valeurs \(n+d\) suivantes, dont certaines ont une signification spéciale :

      En \(32\) bits
      Type
      \(n\) \(d\) \(n+d\)
      \(\pm 0\)
      ou nombre dénormalisé
      \(-127\) \(127\) \(-127+127=0\)
      \(=0000\, 0000\)
      \(\pm \infty\)
      ou les NaN
      \(128\) \(127\) \(128+127=255\)
      \(=1111\, 1111\)
      nombre normalisé \(-126 \le n \le 127\) \(127\) \(1\le n+d \le 254\)

    • Globalement, donc, La norme \(IEEE-754\) sur \(32\) bits permet de stocker sur \(N=8\) bits, des exposants \(n\) tels que :

      \(-2^{N-1}+1 \le n \le 2^{N-1}\)

      \( \begin{alignat}{2} -2^{7}+1 &\leq n &\leq & +2^{7} \\ -128+1 &\leq n &\leq & 128 \\ \end{alignat} \)
      \(-127 \leq n \leq 128\)\(\,\,\, \Leftrightarrow \, \) \(0 \leq n+d \leq 255\) Décalage \(d=\pm 127\)

      Néanmoins, certains de ces exposants \(n+d\) sont réservés et peuvent représenter plusieurs choses :

      • \(n=-127\) \(\Leftrightarrow n+d=0=0000\,\,0000\) correspond à :
        • aux nombres \(\pm 0\) (lorsque \(f=0\)) ou
        • à des nombres dénormalisés càd proches de zéro (lorsque \(f\ne 0\))
      • \(n=128\) \(\Leftrightarrow n+d=255=1111\,\,1111\) correspond à :
        • \(\pm \infty\) (lorsque \(f=0\)) ou
        • des NaNs (lorsque \(f\ne 0\))
      • Les nombres normalisés correspondent à des exposants \(n\) qui vérifient :

        \(-2^{N-1}+2 \le n \le 2^{N-1}-1\)

        \( \begin{alignat}{2} -2^{7}+2 &\leq n &\leq & +2^{7}-1 \\ -128+2 &\leq n &\leq & 128-1 \\ -126 &\leq n &\leq & 127 \\ 1 &\leq n+d &\leq & 254 \end{alignat} \)

  • Enfin, la partie fractionnaire \(f\) est stockée sur \(23\) bits

Mais pourquoi décaler l'Exposant ? 🤔

La norme \(IEEE-754\) n'utilise pas l'encodage par complément à \(2\) pour encoder des exposants positifs ou négatifs, mais une méthode consistant à stocker l'exposant de manière décalée sous la forme d'un nombre non signé. On pourrait se demander pourquoi ? C'est principalement parce que les comparaisons entre deux flottants ainsi représentés sont BEAUCOUP plus simples qu'en complément à \(2\).

Notation \(IEEE-754\) vs Complément à \(2\)

Normalement, la représentation binaire usuelle des nombres entiers signés sur \(N=8\) bits (en complément à \(2\)), permet de stocker des exposants \(n\) (nombres entiers signés) tels que :

\(-2^{N-1} \le n \le 2^{N-1}-1\)
\(-2^7 \le n \le 2^7-1\)
\(-128 \le n \le 127\)
La norme \(IEEE-754\) est donc inspirée du complément à \(2\), mais elles admettent les différences suivantes :

  • La plage des exposants d'\(IEEE-754\) est décalée d'un cran vers la droite (\(-127\le n \le 128\)) par rapport à celle du complément à \(2\) (\(-128\le n \le 127\))
  • IEEE-754 stocke un exposant décalé/biaisé \(n+d\) (non signé) et non pas l'exposant \(n\) (signé) : Les comparaisons entre nombres flottants sont ainsi bien plus simple (comme dit plus haut)
  • Les extrémités d'\(IEEE-754\) (\(-127\) et \(128\)) ont des significations réservées, contrairement au complément à \(2\)

Exemples de Calculs⚓︎

Encodage IEEE-754 de nombres décimaux sur \(32\) bits⚓︎

Conversion Nombre décimal en base \(10\) \(\rightarrow\) Binaire \(IEEE-754\), sur \(32\) bits

On se donne le nombre décimal en base \(10\) suivant:

\(x=-48,15625\)
que l'on souhaite coder sur \(32\) bits, en simple précision, selon la norme \(IEEE-754\). Commençons par déterminer la Notation Binaire Scientifique :

  • \(x\lt0\) donc \(s=1\)
  • Détermination de l'exposant \(n\) et de la mantisse \(f\) : Pour cela, il faut convertir le nombre décimal \(48,15625\) en nombre binaire à virgule.

    • On sépare le nombre \(48,15625\) en deux: sa partie entière \(48\) et sa partie fractionnaire \(0,15625\).
    • On convertit la partie entière en binaire: \(48_2=110000_2\)
    • On convertit la partie fractionnaire décimale (en base 10) en partie fractionnaire binaire de la manière suivante:

      Convertir une partie Fractionnaire Décimale en partie Fractionnaire Binaire

      On multiple \(f\) par \(2\), de manière répétée, en conservant pour chaque nouveau résultat obtenu :

      • la (nouvelle) partie entière du résultat (forcément \(0\) ou \(1\))
      • la (nouvelle) partie fractionnaire (encore notée \(f\)) du résultat

      ...jusqu'à parvenir (obligatoirement) à l'une des \(3\) situations suivantes :

      • jusqu'à ce que \(f=0\) (Si le nombre binaire à virgule tombe juste, comme ici)
      • jusqu'à ce que \(f\) se répète (s'il est illimité périodique : nombre binaire rationnel)
      • jusqu'à ce qu'on en aie marre (s' il est illimité non périodique : nombre binaire irrationnel)

      \( \begin{align} 0,15625\times2 & =\textbf{0},3125 \\ 0,3125\times2 & =\textbf{0},625 \\ 0,625\times2 & =\textbf{1},25 \\ 0,25\times2 & =\textbf{0},5 \\ 0,5\times2 & =\textbf{1},0 \\ 0,0\times2 & =\textbf{0},0 \end{align} \)
      La partie fractionnaire binaire est alors constituée des parties entières des résultats (marquées en gras, lues de haut en bas), càd :
      \( \begin{align} 0,15625_{10} & = 0,001010_2 \\ & = 0\times2^{-1}+0\times2^{-2}+1\times2^{-3}+0\times2^{-4}+1\times2^{-5}+0\times2^{-6} \end{align} \)

      (un bon réflexe consiste à vérifier ce résultat, avec Python par exemple)

    • Le nombre décimal en base \(10\) s'écrit donc en base \(2\) :
      \(x=48,15625_{10}=110000,001010_2\)

    • Notation Binaire Scientifique : il faut donc décaler la virgule à gauche de \(n=5\) crans ce qui revient à l'écrire sous la forme \(x=1,f\times2^n=1,10000001010\times2^5\).
      Donc \(f=10000001010\) et \(n=5\). donc \(x=(-1)^1\times1,10000001010\times2^5\)

Enfin, pour respecter la norme \(IEEE-754\),

  • on décale l'exposant \(n\) de \(d=+127\) \(\quad\) PUIS on code l'exposant biaisé \(n+d\) en binaire:
    \(n+d=5+127=132_{10}=10000100_2\)
  • on complète la partie fractionnaire \(f\) avec des \(0\) jusqu'à \(23\) bits en simple précision (\(32\) bits), de sorte que finalement: \(f=\textbf{10000001010} 000000000000\)

Conclusion: Le nombre décimal \(x=-48,15625\) est donc encodé comme suit avec la norme \(IEEE-754\) :

\(1 \,\,\,\, 10000100 \,\,\,\,10000001010000000000000\)

signe \(\,\,\) exposant \(\,\,\,\,\) (partie fractionnaire)\(\,\,\,\,\)
Vérification \(\rightarrow\) sur ce convertisseur IEEE-754 en ligne

Ex

De la même manière que l'exemple précédent, encoder sur \(32\) bits en suivant la norme IEEE-754 les nombres réels suivants:

  1. \(x=0,1\)
  2. \(x=0,25\)
  3. \(x=\dfrac 13\)

Décodage de nombres IEEE-754 sur \(32\) bits⚓︎

Conversion Binaire \(IEEE-754\) \(\rightarrow\) nombre décimal en base \(10\), sur \(32\) bits

On se donne le mot binaire \(IEEE-754\) sur \(32\) bits suivant:

\[x = 1 \,\, 01111011 \,\, 11011100100000000000000\]

dont on veut savoir à quel nombre décimal, en base \(10\), il correspond.
Ce nombre représente le nombre décimal \(x\) en base \(10\) calculé via la Notation Binaire Scientifique:

  • Signe \(s=(-1)^1=-1\)
  • on décale l'exposant biaisé \(n+d\) de \(-d=-127\) (pour retrouver \(n\))

\(\begin{align} n & = (n+d)-d \\ &= (2^6+2^5+2^4+2^3+2^1+2^0)-127 \\ & = (64+32+16+8+2+1)-127 \\ & = 123-127 \\ & = -4 \end{align} \)

  • mantisse :

\(\begin{align} m &= 1+f \\ &= 1+2^{-1}+2^{-2}+2^{-4}+2^{-5}+2^{-6}+2^{-9} \\ &= 1,861328125 \end{align}\)

Conclusion: le nombre décimal représenté/stocké est

\(x=(-1)^s\times1,f\times2^{n-d}=-1,861328125\times2^{-4}=-0,1163330078125\)
Vérification \(\rightarrow\) sur ce convertisseur IEEE-754 en ligne

Sur \(64\) bits / binary\(64\) / Double Précision⚓︎

Encodage 1+11+52⚓︎

La représentation \(IEEE-754\) des nombres flottants sur \(64\) bits, appelée double précision, ou binary64 se décompose en un triplet \((s,n,f)\) issu initialement de la Notation Binaire Scientifique, mais avec les adaptations/précisions suivantes :

Pour 64 Bits

\(1+11+52=64\)

  • \(s\) est (stocké sur) \(1\) bit de signe :
    • \(s=0\) si \(x>0\) (car \((-1)^0=+1\)), ou bien
    • \(s=1\) si \(x<0\) (car \((-1)^1=-1\))
  • l'exposant \(n\) est stocké sur \(N=11\) bits :

    • Pour commencer, dans la norme \(IEEE-754\), les \(N=11\) bits de l'exposant entier \(n\) (à priori signé) ne sont pas utilisés pour stocker directement l'exposant \(n\) issu de la Notation Binaire Scientifique, mais plutôt un exposant décalé/biaisé \(n+d\) d'une quantité/décalage \(d = 2^{N-1}-1= 2^{10}-1 = 1023\) (de sorte qu'il devienne un entier non signé).
    • Ensuite, La norme \(IEEE-754\) définit le stockage des valeurs \(n+d\) suivantes, dont certaines ont une signification spéciale :

      En \(64\) bits
      Type
      \(n\) \(d\) \(n+d\)
      \(\pm 0\)
      ou nombre dénormalisé
      \(-1023\) \(1023\) \(-1023+1023=0\)
      \(=000\, 0000\, 0000\)
      \(\pm \infty\)
      ou les NaN
      \(1024\) \(1023\) \(1024+1023=2047\)
      \(=111\, 1111\, 1111\)
      nombre normalisé \(-1022 \le n \le 1023\) \(1023\) \(1\le n+d \le 2046\)

    • Globalement, donc, La norme \(IEEE-754\) sur \(64\) bits permet de stocker sur \(N=11\) bits, des exposants \(n\) tels que :

      \(-2^{N-1}+1 \le n \le 2^{N-1}\)

      \( \begin{alignat}{2} -2^{10}+1 &\leq n &\leq & +2^{10} \\ -1024+1 &\leq n &\leq & 1024 \\ \end{alignat} \)
      \(-1023 \leq n \leq 1024\)\(\,\,\, \Leftrightarrow \, \) \(0 \leq n+d \leq 2047\) Décalage \(d=\pm 1023\)

      Néanmoins, certains de ces exposants \(n+d\) sont réservés et peuvent représenter plusieurs choses :

      • \(n=-1023\) \(\Leftrightarrow n+d=0=000\,\, 0000\,\,0000\) correspond à :
        • aux nombres \(\pm 0\) (lorsque \(f=0\)) ou
        • à des nombres dénormalisés càd proches de zéro (lorsque \(f\ne 0\))
      • \(n=1024\) \(\Leftrightarrow n+d=2047=111\,\, 1111\,\,1111\) correspond à :
        • \(\pm \infty\) (lorsque \(f=0\)) ou
        • des NaNs (lorsque \(f\ne 0\))
      • Les nombres normalisés correspondent à des exposants \(n\) qui vérifient :

        \(-2^{N-1}+2 \le n \le 2^{N-1}-1\)

        \( \begin{alignat}{2} -2^{10}+2 &\leq n &\leq & +2^{10}-1 \\ -1024+2 &\leq n &\leq & 1024-1 \\ -1022 &\leq n &\leq & 1023 \\ 1 &\leq n+d &\leq & 2046 \end{alignat} \)

  • Enfin, la partie fractionnaire \(f\) est stockée sur \(52\) bits

Exercice⚓︎

Ex

  1. Montrer qu'en simple précision (\(32\) bits), les nombres flottants positifs peuvent représenter les nombres décimaux entre \([10^{-38};10^{38}]\) environ
  2. Montrer qu'en double précision (\(64\) bits), les nombres flottants positifs peuvent représenter les nombres décimaux entre \([10^{-308};10^{308}]\) environ

Historique de la Norme IEEE 754⚓︎

Normes IEEE pour l'arithmétique en virgule flottante.

Date Norme Apports
\(2019\) \(IEEE-754-2019\)
\(2008\) \(IEEE-754-2008\)
\(1985\) \(IEEE-754-1985\)

Notes et Références⚓︎

Notes⚓︎

Références⚓︎