Les flottants☘
En base b, un flottant est un nombre de la forme $$ s \times m \times b^e$$
- s est le signe (+ ou -) ;
- m est la mantisse. C'est un nombre à p chiffres, avec exactement un chiffre (non nul) avant la virgule ;
- e est l'exposant, avec e_{min} \leq e \leq e_{max}.
Attention
Les nombres p, e_{min} et e_{max} sont des nombres écrits en base b et donnés dès le départ.
Ils permettent de définir une norme (une convention) de représentation des flottants en base b.
Note
La définition donnée ci-dessus n'est pas tout à fait la définition générique des flottants,
mais nous nous tiendrons à cette approche pour simplifier.
Il s'agit donc de nombres pour lesquels nous imposons l'écriture en notation scientifique.
Les nombres de chiffres pour m et pour e sont bornés : cela permet de tenir compte des contraintes des nombres en machine qui seront toujours représentés avec le même nombre, nécessairement fini, de bits (sur les machines actuelles, usuellement 64 bits).
Un exemple en base 10☘
-
Faire la liste des flottants en imposant p = 2, e_{min} = -1 et e_{max} = 1.
Réponse
-
Les mantisses possibles sont :
- 1,0 ; 1,1 ; 1,2 ; ... ; 1,9
- 2,0 ; 2,1 ; 2,2 ; ... , 2,9
- ...
- 9,0 ; 9,1 ; 9,2 ; ... ; 9,9
-
Les exposants possibles sont -1, 0 et 1.
-
Les flottants tels que p = 2, e_{min} = -1 et e_{max} = 1 sont donc :
-
Les nombres :
-
0,10 ; 0,11 ; 0,12 ; ... ; 0,19 (c'est-à-dire 1,0 × 10-1 ; 1,1 × 10-1 ; 1,2 × 10-1 ; ... ; 1,9 × 10-1)
-
0,20 ; 0,21 ; 0,22 ; ... , 0,29 (c'est-à-dire 2,0 × 10-1 ; 2,1 × 10-1 ; 2,2 × 10-1 ; ... ; 2,9 × 10-1)
-
...
-
0,90 ; 0,91 ; 0,92 ; ...; 0,99 (c'est-à-dire 9,0 × 10-1 ; 9,1 × 10-1 ; 9,2 × 10-1; ... ; 9,9 × 10-1)
-
-
Les nombres :
-
1,0 ; 1,1 ; 1,2 ; ... ; 1,9 (c'est-à-dire 1,0 × 100 ; 1,1 × 100 ; 1,2 × 100 ; ... ; 1,9 × 100)
-
2,0 ; 2,1 ; 2,2 ; ... ; 2,9 (c'est-à-dire 2,0 × 100 ; 2,1 × 100 ; 2,2 × 100 ; ... ; 2,9 × 100)
-
...
-
9,0 ; 9,1 ; 9,2 ; ... ; 9,9 (c'est-à-dire 9,0 × 100 ; 9,1 × 100 ; 9,2 × 100 ; ... ; 9,9 × 100)
-
-
Les nombres :
-
10 ; 11 ; 12 ; ... ; 19 (c'est-à-dire 1,0 × 101 ; 1,1 × 101 ; 1,2 × 101 ; ...; 1,9 × 101)
-
20 ; 21 ; 22 ; ... ; 29 (c'est-à-dire 2,0 × 101 ; 2,1 × 101 ; 2,2 × 101 ; ... ; 2,9 × 101)
-
...
-
90 ; 91 ; 92 ; ... ; 99 (c'est-à-dire 9,0 × 101 ; 9,1 × 101 ; 9,2 × 101 ; ... ; 9,9 × 101)
-
-
Et les opposés de ces nombres.
-
-
-
Que pout-on dire de l'écart entre un nombre et le nombre suivant avec cette représentation ?
nombre suivant
On peut déjà remarquer que la notion de « nombre suivant » a un sens alors qu'elle n'en a pas avec les nombres réels.
Une solution
Raisonnons uniquement sur les positifs.
Entre deux « petits » nombres consécutifs (par exemple entre 0,10 et 0,11), l'écart est 0,01.
Entre deux « grands » nombres (par exemple 90 et 91), l'écart est 1.
Conséquences de cet exemple☘
Avec la représentation précédente, tous les réels de l'intervalle [0,10; 0,105[ (ouvert ou fermé à droite, choix possible) seront représentés par le même flottant : 1,0 \times 10^{-1}.
Et tous les réels de l'intervalle [10; 10,5[ seront représentés par le flottant 1,0 \times 10^1.
Ainsi, suivant qu'il s'agit de nombres proches de 0 ou éloignés de 0, chaque réel aura pour représentant dans les flottants un nombre plus ou moins éloigné de lui. Ou en d'autres termes, un même flottant représentera chacun des réels d'un intervalle plus ou moins grand.
Remarque
La remarque porte sur l'écart absolu (valeur absolue de la différence entre
le nombre et son représentant flottant).
Les écarts relatifs (valeur absolue du quotient (écart absolu)/nombre) sont
par contre « un peu plus constants » pour les ensembles de
flottants usuellement utilisés en machine (et c'est là une propriété
importante pour le calcul scientifique en machine).
La conséquence la plus importante est qu'on ne peut pas attendre que les opérations sur les flottants aient les mêmes propriétés que les opérations sur les réels.
Exemple
Nous avons déjà constaté cela. Par exemple la non commutativité avec:
>>> 1 + 10**(-16) -1
0.0
>>> 1 - 1 + 10**(-16)
1e-16
Une explication
On a:
>>> 1+10**(-16)
1.0
tandis que
>>> 0 + 10**(-16)
1e-16
Sans rentrer dans les détails, on peut reprendre ce qui est exposé plus haut :
10**(-16)
est proche de 0 et aura un représentant flottant assez fidèle,1 + 10**(-16)
est plus éloigné de 0 et les réels entre1
et1 + 10**(-16)
auront tous1
pour représentants.
Dans 1 + 10**(-16) -1
, on évalue 1 + 10**(-16)
qui donne 1
puis
on évalue 1 - 1
, on obtient 0
.
Dans 1 - 1 + 10**(-16)
, on évalue 1 - 1
qui donne 0
puis on
évalue 0 + 10**(-16)
, on obtient 10**(-16)
.
Flottants binaires et norme IEEE 754☘
Les flottants binaire sont représentés en général en machine suivant la norme IEEE 754. Ce nombre est de la forme :
Dans le format binary64, les flottants sont codés sur 64 bits selon le schéma ci-dessous :
1 | 11 | 52 | |
signe (s) | exposant (e) | mantisse (m) |
- Le premier bit (à gauche) représente le signe s : 0 pour un positif, 1 pour un négatif ;
- Les 11 bits suivants représentent l'exposant e.
Pour connaître la valeur de l'exposant représenté, on traduit la suite de bits par un entier positif (écrit en binaire) puis on enlève le décalage d de valeur 1023 (on enlève 127 dans un codage 32 bits). - Les 52 bits restants correspondent aux bits se trouvant après la virgule du
flottant.
C'est la mantisse m privée du 1 qui se trouve avant la virgule (car il y a forcément un 1 devant la virgule en binaire).
Exemple☘
Quel nombre décimal est représenté par le mot de 64 bits suivant :
Une solution
- Le bit de poids fort est 1 donc le signe est négatif
- L'exposant est e = 2^{10}+2^2+2^1 - 1023 = 1030 - 1023 = 7
- La mantisse est m = 1 + \frac{1}{2^1} + \frac{1}{2^3} + \frac{1}{2^5} + \frac{1}{2^6} + \frac{1}{2^8} + \frac{1}{2^9} = 1,677734375
- Le nombre décimal représenté est -1,677734375 \times 2^7 = -214,75.
Valeurs particulières☘
Un certain nombre de codes sont réservés pour représenter des cas particuliers :
0 11111111111 0000000000000000000000000000000000000000000000000000☘
Ce code (0 suivi de onze 1, suivis de cinquante-deux 0) représente +\infty (+inf).
1 11111111111 0000000000000000000000000000000000000000000000000000☘
Ce code (1 suivi de onze 1, suivis de cinquante-deux 0) représente -\infty (-inf).
1 11111111111 1111111111111111111111111111111111111111111111111111☘
Ce code (soixante-quatre bits à 1) représente NaN
(not a number).
0 00000000000 0000000000000000000000000000000000000000000000000000☘
Ce code (soixante-quatre bits à 0) représente 0.
1 00000000000 0000000000000000000000000000000000000000000000000000☘
Ce code (Un bit à 1 suivi de soixante-trois bits à 0) représente également 0 (-0).
Et dans l'autre sens?☘
Si l'on dispose du code de soixante-quatre bits représentant un flottant sous le format binary64 de la norme IEEE 754, il est facile d'en déduire le nombre représenté (il suffit d'appliquer la définition de ce format comme présenté plus haut).
Ce qui est moins évident est, connaissant un nombre réel, de savoir par quel flottant il va être représenté en machine.
Rappelons notamment qu'un même flottant représente en fait une infinité de réels distincts. Il y a également beaucoup de réels qui ne sont tout simplement pas représentables en machine suivant ce format (trop grand, ou trop proche de zéro).