Virgule flottante norme IEEE 754
La norme IEEE 754, très utilisée, propose de représenter un nombre en virgule flottante sur un nombre fini de bits. C'est une norme très répandue dans les ordinateurs modernes. Dans ce chapitre, nous allons en voir les grandes lignes, sans en voir tous les détails. Pour plus de simplicité, ce cours désigne les nombres représentés en suivant la norme IEEE 754 pour le nombres à virgule flottante par le nom flottant.
La norme IEEE 754 représente un nombre flottant en trois parties, comme vu dans le chapitre précédent.
- Le bit de poids fort est utilisé pour le signe.
- Les \(n\) bits suivants sont utilisés pour l'exposant.
- Les \(m\) bits restants (de poids faible) sont utilisés pour la mantisse.
TODO (prof) ajouter schéma ici
Dans le cas d'un flottant 32 bits, on a \(n = 8\) et \(m = 23\)
Exposant biaisé
L'exposant est un entier relatif en base 2. Pour simplifier les comparaisons entre flottants, il est dans la représentation ramené à une valeur strictement positive ou nulle à l'aide d'un biais.
Pour un exposant \(e\) sur \(n\) bits, le biais est de \(2^{n-1} - 1\).
Par exemple, pour un flottant en 32 bits, \(n = 8\), et donc le biais est de \(2^7 - 1\) = \(127\). L'exposant est alors compris entre -127 et +128, mais est stocké sous forme d'un entier, l'exposant biaisé, de 0 à 255.
TODO (prof) ajouter schéma ici
A noter que la valeur maximale de l'exposant biaisé, à savoir 255 pour les flottants sur 8 bits, et \(2^{n} - 1\) sur des flottants sur \(n\) bits, est réservée pour coder des valeurs spéciales.
Bit implicite de la mantisse
La mantisse un entier à virgule fixe, avec 1 bit pour la partie entière (\(b_i\)), et \(m\) bits pour la partie fractionnaire:
TODO (prof) ajouter schéma ici
Seuls les \(m\) bits de la partie fractionnaire sont stockés dans la représentation du nombre, et le bit \(b_i\) est déterminé de manière implicite :
- Si l'exposant biaisé est 0, alors \(b_i = 0\)
- Sinon, \(b_i = 1\)
Dans ce cours, on considérera uniquement des nombres qui auront \(b_i = 1\), sauf zéro.
Valeurs spéciales
Zéros
La valeur zéro est représentée par un exposant biaisé à 0, et une mantisse à zéro. Comme le signe n'est pas pris en compte dans cette définition, il y a deux représentations de zéro : zéro "négatif" (\(-0\)) et zéro "positif" (\(+0\) ou \(0\)).
Par exemple le code python suivant :
affiche
Cette différence est parfois utile pour des calculs tenant compte de l'approximation.
Infinis
L'exposant biaisé est à sa valeur maximum (255 dans le cas d'un flottant 32 bits), et la mantisse à 0, codent un infini. Là encore, le signe autorise des infinis positifs et négatifs.
On peut créer un infini en Python en utilisant la fonction float
, à laquelle on donne "inf"
ou "-inf"
en argument.
affiche
Les infinis positifs et négatifs sont considérés respectivements comme plus grands et plus petit que toutes les autres valeurs que nous avons vues jusqu'à présent (les valeurs numériques).
Les infinis sont absorbants pour toutes les valeurs numériques sauf \(0\).
affiche
nan
Finalement, si la mantisse est différente de 0 et que l'exposant biaisé est à sa valeur maximale (255 pour les flottants 32 bits), la valeur codée est nan, pour (Not a Number, pas un nombre).
C'est une valeur utilisée, entre autres, comme résultat de certains calculs qui n'ont pas de sens. Par exemple, multiplier un infini par zéro :
affiche
La valeur nan est absorbante pour toutes les autres valeurs des flottants :
affiche
Le codage de nan a beaucoup d'autres subtilités que nous détaillerons pas dans le cours.
Tailles
Voici les tailles de flottant qu'on trouve dans la norme IEEE 754 :
nom | bits | signe | exposant | mantisse |
---|---|---|---|---|
demi précision | 16 | 1 | 5 | 11 |
simple précision | 32 | 1 | 8 | 23 |
double précision | 64 | 1 | 11 | 52 |
quadruple précision | 128 | 1 | 15 | 112 |
octuple précision | 256 | 1 | 19 | 236 |
Les formats quadruple et octuple précision sont très rarement implémentés dans les processeurs (sous forme de circuits), parce qu'ils sont très rarement nécessaires. Par défaut, Python utilise des flottants en double précision.
Voici les plages (approximatives) de valeurs en notation scientifique en base 10 qui peuvent être réprésentées sur chaque format :
nom | valeurs d'exposant | chiffres mantisse |
---|---|---|
demi précision | \([-4;4]\) | 3 |
simple précision | \([-38;38]\) | 7 |
double précision | \([-308;308]\) | 16 |
quadruple précision | \([-4966;4932]\) | 34 |
octuple précision | \([-78984;78913]\) | 71 |
Activité : les limites
Cherchez des grandeurs concrètes, très grandes ou petites, et qui sont le plus proches possibles des limites des représentations en simple et double précision.
Grandeur contrète veut dire qu'elle doit être utilisée dans le monde réel.
- La masse du soleil
- Le nombre de pages écrites par l'humanité
- Les stats d'un boss dans un jeu vidéo
- ...
Conversion flottant IEEE 754 vers décimal
TODO (prof) reecrire ça comme relatif à la conversion générale
Remarque : dans la suite, 0...
indique que l'on remplit de zéros les bits restants dans la représentation du nombre.
La conversion IEEE 754 en base 2 vers base 10 est très similaire à la méthode vue précédemment pour les représentations à virgule flottante. Il faut juste tenir compte du biais de l'exposant et du bit implicite de la mantisse.
TODO (prof) ajouter schéma ici ?
Pour convertir le flottant IEEE 754 sur 32 bits suivant en sa valeur en base 10 :
s | exposant biaisé | mantisse |
---|---|---|
1 |
1000 0001 |
1001 0... |
On commence par calculer la valeur en base 10 de l'exposant biaisé:
On lui soustrait son biais, ce qui nous donne la valeur de l'exposant. Pour 32 bits, le biais est de 127 :
On calcule ensuite la valeur en base 10 de la mantisse, comme si elle avait une virgule fixe en base 2. On oublie pas d'ajouter un 1 (ou un 0, si l'exposant biaisé est 0) à droite.
On détermine le signe. Ici, le bit de signe est 1, donc le signe est \(-\).
On applique la formule des virgules flottantes en base 2 :
Ce qui donne :
Exercice : flottant vers base 10
Convertissez le nombre flottant IEEE 754 sur 32 bits en sa représentation en base 10.
Rappel : le biais de l'exposant est de 127 pour un flottant IEEE 754 32 bitS.
Ce flottant se décompose comme suit :
| s | exposant biaisé | mantisse |
| :---: | :-------------: | :-------: |
| 1
| 1000 1001
| 1110...
|
N'oubliez pas de débiaiser l'exposant
Pensez également à ajouter le bit des unités de la mantisse, c'est à dire un 1 à gauche..
Le bit de signe est 1, le nombre est donc négatif.
On calcule maintenant la valeur en base 10 de l'exposant biaisé.
On débiaise l'exposant :
On reconstitue la valeur de la mantisse, en ajoutant la virgule et un 1 à gauche. On retire aussi les zéros à droite inutiles :
devientOn calcule sa valeur décimale.
On utilise ensuite la formule de la virgule flottante pour reconstituer la valeur.
Conversions décimal vers flottant IEEE 754
TODO (prof) reecrire ça comme relatif à la conversion générale ?
Remarque : dans la suite, 0...
indique que l'on remplit de zéros les bits restants dans la représentation du nombre.
La conversion décimal vers IEEE 754 est très similaire à la conversion que nous avons précédemment, de la base 10 vers une virgule flottante en base 2. Il nous faut juste ajouter un biais à l'exposant et penser au bit implicite de la mantisse.
Pour convertir \(-10,3125\) en base 10 vers sa représentation flottante IEEE 754 en base 2 sur 32 bits :
On commence par convertir le nombre en base 2 avec virgule fixe, en convertissant successivement sa partie entière et sa partie fractionnaire :
Partie entière :
Conversion partie fractionnaire :
\(p\) | \(q = 2p\) | \(q \geq 1\) ? | \(q - 1\) | \(b\) |
---|---|---|---|---|
\(0,3125\) | \(0,625\) | non | - | \(0\) |
\(0,625\) | \(1,25\) | oui | \(0,25\) | \(1\) |
\(0,25\) | \(0,5\) | non | - | \(0\) |
\(0,5\) | \(1,0\) | oui | \(0\) | \(1\) |
\(0\) | stop | - | - | - |
On arrête la conversion quand le tableau se finit ou quand on dépasse le nombre de bits présents dans la mantisse.
On déduis la représentation virgule fixe binaire du nombre :
On décale la virgule pour qu'il ne reste qu'un seul chiffre dans la partie entière, et que ce chiffre soit 1 (a noter, le chiffre peut être zéro dans certains cas qu'on ne vous demandera pas de traiter dans ce cours). Un décalage de la virgule vers la gauche compte en positif, un décalage de la virgule vers la droite compte en négatif. On en déduis alors une notation en virgule flottante :
On ajoute le biais à l'exposant. Dans le cas d'un flottant 32 bits, le biais est de 127:
On convertis l'exposant biaisé en base 2 :
Finalement, on déduis la valeur de la mantisse sur 23 bits en retirant le bit de la partie entière, ce qui nous donne la représentation complète du nombre :
s | exposant | mantisse |
---|---|---|
1 |
1000 0010 |
0100 1010... |
TODO (prof) ajouter des exercices ici
FLOPS
Les operations sur les flottants demandent en général des circuits beaucoup compliqués que pour les opérations sur les entiers, et sont pourtant nécessaires à de nombreuses applications. Parmi ces dernières, on compte le calcul scientifiques, mais ausi les jeux vidéos 3D et de nombreux jeux vidéos en 2D.
Une des manières d'évaluer la puissance de calcul d'un processeur ou d'un ordinateur est donc de mesurer le nombre d'opérations flottantes qu'il peut réaliser par seconde. Le FLOPS (FLoating-point Operations Per Second, en français Opérations en virgule flottante par seconde) est l'unité de mesure de cette performance.
La puissance de calcul des ordinateurs augmente considérablement chaque année.
Ainsi, le plus puissant supercalculateur de 1964, Control Data 6600, avait une puissance de 3,3 MFLOPS environ ( MégaFLOP, 1 million d'opérations flottantes par seconde)
En 2022, le supercalculateur Frontier affiche une puissance de 1,1 EFLOPS (ExaFLOP, \(1\times 10^18\), un milliard de milliards d'opérations flottantes par seconde).
Dans le même temps, les processeurs pour ordinateurs personnel haut de gamme, comme le AMD Ryzen 3700X (2019) ou le Intel i7-10700k (2020) ont une puissance aux alentours de 500 GFLOPS (GigaFLOP, 1 milliard d'opérations par seconde), ce qui est du même ordre que ASCI Red, supercalculateur le plus puissant du monde en 1996.
Les GPU (Graphics Processing Unit, en français processeur graphique), majoritairement accessible au grand public sous forme de cartes graphiques, sont des circuits spécialisés dans le traitement de nombre flottants. Ainsi, les GPU jeu vidéo haut de gamme AMD Radeon RX 5700 XT (2019) et Nvidia GeForce RTX 2080 (2019) ont une puissance d'environ 9 TFLOP (TéraFLOP, 1000 milliards d'opérations par seconde). C'est comparable au meilleur supercalculateur en l'an 2000, IBM ASCI White.