Dans les séquences précédentes, nous avons vu que le langage Python permet de calculer avec des nombres déchmaux particuliers appelés nombres flottants.
Nous allons voir dans cette séquence que ces nombres ont un encodage très compact, sur 32 ou 64 bits, qui permet de représenter des nombres très grands, bien au-delà de ce qu'il est possible de représenter avec un codage des entiers sur le même nombre de bits, mais également de très petits nombres.
L'encodage des nombres flottants est inspiré de
l'écriture scientifique des nombres décimaux qui se compose d'un signe (+ ou - }, d’un nombre décimal m, appelé mantis ompris dans l'intervalle [ 1 , 10 [ (1 inclus et 10 exclu) et d'un entier relatif n appelé exposant.
Par exemple, avec cette notation,
2156 s'écrit +2,156 x 103
Mettre le résultat ici de la requête sql.
Ainsi, de manière générale, l'écriture scientifique d’un nombre décimal est de la forine :
avec m la mantis et n l'exposant.
On note en toute rigueur que le nombre 0 ne peut pas être représenté avec cette écriture.
La représentation des nombres flottants ct les opérations arithmétiques qui les accompagnent ont été définies dans la norme internationale IEEE 754.
C'est la norme la plus couramment utilisée dans les ordinateurs.
Selon la précision ou l'intervalle de représentation souhaité, la norme définit un format de données sur 32 bits, appelé single précision où binary32, ct un autre sur 64 bits, appelé double précision où binary64.
Il existe également des versions étendues de ces formats dont nous ne parlerons pas ici.
Dans les deux cas, la représentation d'un nombre fottant est similaire à l'écriture scientifique d’un nombre décimal, À savoir une décomposition en trois parties : un signe s. une mantisse m el un exposant n.
De manière générale, un nombre flottant à la forme suivante.
(-1)S x m x 2( n - d )
Les différences entre la norme IREE 754 ot l'écriture scientifique sont premièremont que la base choisie est maintenant la base 2, ensuite que la mantisse est donc dans l'intervalle [ 1 , 2 [, et enfin que l'exposant n'est décalé (ou biaisé) d'une valcur d qui dépend du format choisi (32 ou 64 bits).
Dans le format 32 bits, représenté par ie schéma ci-dessous, le bit de poids fort est utilisé pour représenter le signe s (avec 0 pour le signe +), les 8 bits suivants sont réservés pour stocker la valeur de l'exposant n et les 23 servent à décrire la mantisse.
1bit | 8bits | 23bits
signe|exposant| mantisse
1 |01010111|01010101 01110111 1101011
Afin de représenter des exposants positifs et négatifs, la norme IEEE 754 n'utilise pas l'encodage par complément à 2 des entiers relatifs, mais une technique qui consiste à stocker l'exposant de manière décalée sous la forme d'un nombre non signé.
Ainsi, l'exposant décalé n est entre 0 et 255. Pour le format un entier sur 8 bits qui représente des entiers
32 bits, l'exposant n est décalé avec d = 127, ce qui permet de représenter des 127,128. Néanmoins, les valeurs 0 et 255 exposants signés dans l'intervalle
étant réservées pour représenter des nombres particuliers (voir ci-dessous), les exposants signés sont donc ceux de l'intervalle [-126, 127].
La mantisse m étant toujours comprise dans l'intervalle [1 , 2 [, elle représente un nombre de la forme 1 xx xx c'est-à-dire un nombre commeparaZU.1. Norme IEEE /b4 253$
de précision, les 23 bits dédiés à la mantisse sont uniquement utilisés pour
représenter les chiffres après la virgule, qu'on appelle la fraction. Ainsi, si
les 23 bits dédiés à la mantisse sont b1 bo... b23, alors la mantisse représente
le nombre
1+bhx2 4h x 224... bg x 2729
Par exemple, le mot de 32 bits suivant
signe exposant fraction
RSS PRE ——————
T 10000110 10101101100000000000000
représente le nombre décimal calculé ainsi :
signe = 1!
=
exposant = (2749522) 197
= (128+4+2)—127
= 131-127
imantisse =
Soit, au final, le nombre décimal suivant :
—1,677734875 x 27 = 214,75
Coucernant les deux formats, la différence entre les encodages 32 et 64
bits est simplement la valeur d du décalage pour l'exposant et le nombre de
bits alloués pour la fraction f de la mantisse m et l’exposant n. Le tableau
ci-dessous résume les deux encodages.
! Bbits [| 23b#s |(-1x1/xate nn |
1lbits | S2bits [(-1) x1,f x 21671029)
Aïnsi, en simple précision (32 bits), les nombres flottants positifs peuvent
représenter les nombres décimaux compris (approximativement) dans l'in-
tervalle 107%, 105$], tandis qu'en double précision, l'intervalle des nombres254 Chapitre 20. Représentation approximative des nombres réels
Valeurs spéciales. Tel que nous l'avons défini jusqu'ici, le format des
nombres Aottants ne permet pas de représenter le nombre 0. En effet, puisque
un nombre flottant sur 32 bits correspond à la formule (—1}° x 1, / x gte—127), la forme L, f de la mantisse interdit la représentation du 0. Pour remédier
à ce problème, la norme IEEE 754 utilise les valeurs de l'exposant restées
jusqu’à présent inutilisées, à savoir 0 et 235, pour représenter le nombre 0
mais aussi d’autres valeurs spéciales.
Ainsi, le nombre 0 est représenté par le signe 0, un exposant 0 et une
mantisse 0. En fait, la norme reconnaît deux nombres 0 : le Q positif, noté
+6, qui est celui que nous venons de décrire, et le O négatif, noté —0, qui est
celui avec un bé de signe à 1.
La norme permet également de représenter deux infinis, notés —:x et
+oo, en utilisant la valeur 255 de l’exposant el nne mautisse à Ô (le bit de
signe étant utilisé pour représenter le signe de ces infinis). Ces deux infinis
sont utilisés pour indiquer des dépassements de capacité.
Eufin, une valeur spéciale, notée NaN (pour Mot a Number), permet de
représenter les résultats d'opérations invalides comme 0/0, 4/-T où encore
O0 x +50. Cette valeur est encodée avec nn signe à 0, un exposant à 255 et
importe quelle mantisse diflérente de 0.
Les encodages de ces valeurs spéciales sont résumés dans le tableau ci-
dessous.
où 0 0 | +0
1 0 0 —0
0 255 0 | +0
1 255 0 x
0 | 255 £20 NaN
Nombres dénormalisés. Comme nous l'avons vu plus haut, si l'exposant
d’un nombre flottant (sur 32 bits) est compris entre 1 ct 254, alors la valeur
représentée par l'encodage est (—1)$ x 1, f x 2127), Les nombres représen-
. Avec cet encodage, le plus
tés ainsi sont les nombres flottants normal.
petit nombre décimal positif représentable est done 27126 (soit + 107%).
Maintenant, puisque la mantisse est. implicitement de la forme 1. f, il n’y à
pas de nombres représentables dans l'intervalle {0,271%[, alors qu'il y en à
2% dans l'intervalle [1 x 27126,9 x 27167 2 [2-16 97128],
Afin de rééquilibrer la représentation des nombres autour de 0, là norme
IEEE 754 permet d'encoder des nombres de la forme
(—1)° x 0, f x 27126
aver nine mantieer N f enmmeneant imnlicitement nar nn Î Cec nombhrne£U.1. INOFTME IELE 194 299
tants avec un exposant à 0 et une mantisse différente de 0. De cette ma-
s est
nière, la plus petite valeur représentable avec des nombres dénormali
2-23 4 2126 — 9149
Dénormalisés et test d'égalité. Saus les nombres cdénormalisés. les
deux tests 7 — y = Üetr = y ne seraient pas systématiquement équiva-
lents
Arrondis. Ii est important de noter que la représentation des nombres dé-
cimaux par des flottants est une représentation approximative. Par exemple, le nombre décimal 1,6 ne peut pas être représenté exactement avec cet en-
codage. Pour cela, il faut arrondir cette valeur en choisissant le meilleur
nombre flottant pour la représenter.
La norme IEEE 754 définit quatre modes d'arrondi pour choisir le
meilleur flottant :
e au plus près : le Aottant le plus proche de Ja valeur exacte (en cas
d'égalité, on privilégie le flottant pair, c’est-à-dire avec une mantisse
se terminant par 0);
e vers zéro : Le flottant Le plus proche de 0:
e vers plus l'infini : le plus petit flottant supérieur ou égal à la valeur
exacte ;
e vers moins l'infini : le plus grand flottant inférieur où égal à la valeur
exacte,
Le mode d'arrondi par défaut de la norme est au plus près. Par exemple, le
nombre flottant le plus proche de 1,6 est
001111111 10011001100110011001101
qui correspond au nombre décimal
(271497149849 849949 +2 8e
216 + 9 ir + 220 + 2-21 + 273)
2(127—127)
= 1, 60000002384185791015625
Cette opération d'arrondi se propage également aux opérateurs arithrmé-
tiques, En effet, même si deux nombres décimaux sont exactement repré-
sentables avec des flottants, il n'en est pas nécessairement de même pour
le résultat d'une opération entre ces deux nombres. Ainsi, la norme IEEE
754 exige, pour les opérations usuelles (addition, multiplication, soustrac-256 Chapitre 20. Keprésentation approximative des nombres réels
résultat obtenu en appliquant un opérateur sur deux nombres flottants est
le même que celui que l'on obtiendrait en effectuant l'opération en précision
infinie sur ces deux nombres puis en arrondissant.
Mettre le résultat ici (code et figure).
Ils sont représentés selon la norme IEEE 754 double précision (format 64 bits). On peut utiliser la notation décimale ou scientifique pour les définir :
x = 1.6
y = 1.2e-4
print(\"x= \",x)
print(\"y= \",y)
La fonction float() permet de convertir un entier en un flottant.
Inversement, la fonction int() transforme un flottant en un entier simplement en ignorant la partie après la virgule.
x = float(-4)
y = int(5.9)
print(\"x= \",x)
print(\"y= \",y)
Les opérations arithmétiques usuelles s'appliquent également aux flottants.
x = 3.4 + 0.012
y = 1.2 / 2.0
print(\"x= \",x)
print(\"y= \",y)
Il convient également de préciser que l'opérateur de division / produit toujours un résultat flottant, quelque soit le type de ses arguments.
x = 1 / 2
y = 4 / 2
z = 2 / 3.2
print(\"x= \",x)
print(\"y= \",y)
print(\"z= \",z)
Certaines expressions peuvent générer des valeurs spéciales, comme inf ou nan, pour représenter respectivement des dépassements de capacité ou des
opérations non valides.
x = 1e200
print( x * x )
print(x * x * 0)
Des conversions d’entiers vers flottants peuvent être réalisées de manière implicite dans les expressions arithmétiques où un opérateur s'applique à la fois à un entier et un flottant, comme par exemple dans le caleul ci-dessous.
x = 5 * 2.7
print(\"x = \",x)
Ces conversions peuvent provoquer des erreurs qu’il est important de bien différencier des débordements de capacité sur les flottants.
Par exemple, dans le code ci-dessous
y = 10 ** 400
y = y + 0.5
Lève l'erreur suivante :
Traceback (most recent call last):
File \"<stdin>\", line 1, in <module>
OverflowError: int too large to convert to float
La variable y contient un entier après son initialisation à 10 ** 400. Cot entier doit être converti (de manière implicite) en un flottant afin que l’addition y + 0.5 puisse être exécutée, mais cette conversion provoque une erreur.
Mettre le résultat ici (code et figure).
La bibliothèque standard de Python fournit également de nombreuses fonctions mathématiques rassemblées dans un module math.
Pour utiliser les fonctions de cette bibliothèque, il faut tout d'abord charger le module math à l'aide d'une directive d'import.
import math
Les fonctions ou constantes mathématiques de ce module sont ensuite aecessibles on utilisant la notation pointée math.f, où f est le nom de la fonction
{ou constante).
x = math.sqrt(9)
y = math.sin(1.6 * math.pi)
print(\"math.sqrt(9) =\",x)
print(\"math.sin(1.6 * math.pi) =\",y)
Enfin, la fonction print perinet d'afficher des nombres flottants en précisant le nombre de chiffres après la virgule à l'aide d’une chaîne de formatage :
\"%. [precision]f\",
où [precision] est une constante entière (positive).
Pour afficher une valeur v selon un certain formatage, il faut faire suivre la chaîne de % v. comme dans les exemples suivants :
x = 0.12345
print(\"%.2f\" % x)
print(\"%.20f\" % 1.6)
Mettre le résultat ici.
Il faut être très prudent lorsque l'on manipule des nombres flottants. En effet, certaines opérations sur ces nombres n’ont pas les mêmes propriétés que sur les nombres réels ct il ne faut jamais oublier que les calculs sont inexacts.
Par exemple, une simple multiplication comme celle ci-dessous nous montre immédiatement les imprécisions du calcul.
x = 1.2 * 3
print(\"1.2 * 3 =\", x)
En ce qui conecrnc les propriétés des opérations, l'addition et la multiplication ne sont pas associatives, comme on peut le voir dans l’exemple suivant :.
x = 1.6 + (3.2 + 1.7)
print(\"%.20f\" % x)
y = (1.6 + 3.2) + 1.7
print(\"%.20f\" % y)
Ensuite, la multiplication n'est pas distributive par rapport à l'addition, comme on peut le voir ici :
x = 1.5 * (3.2 + 1.4)
print(\"%.20f\" % x)
y = 1.5 * 3.2 + 1.5 * 1.4
print(\"%.20f\" % y)
Au final, ces exemples montrent qu'il est très imprudent d'écrire des programmes dans lesquels on utilise des tests d'égalité entre flottants.
Par exemple, on retiendra que l'inprécision de la représentation des nombres réels conduit par exemple à des résultats surprenants comme :
print(0.1 + 0.2 == 0.3)
Aussi, plutôt que d'écrire un test d'égalité entre deux valeurs flottantes v1 et v2, il ost préférable d'écrire un test d’inégalité |v1-v2| < e entre la valeur
absolue de la différence v1 - v2 et une borne de précision e.
Par exemple, pour tester l'égalité à 10-12 près entre les variables x et y suivantes, on écrira :
x = 0.1 + 0.2
y = 0.3
print(\"x=\",\"%.20f\" % x)
print(\"y=\",\"%.20f\" % y)
print(\"x==y :\",x==y)
print(\"|x-y|<1e-12 ;\",abs(x - y) < 1e-12)
Mettre le résultat ici (code et figure).
Exercice 214 Dounér la représentation flottante en simple précision de 128
ct —32,75. Solution page 485 1
Mettre le résultat ici (code et figure).
Exercice 215 Douuer la valeur décimale des nombres flottants suivants co-
dés en simple précision :
1 01111110 11110000000000000000000
0 10000011 11100000000000000000000.
Sotion page 485 Cl
Mettre le résultat ici (code et figure).
Exercice 216 On tape en Python l'expression arithmétique suivante.
>>> (1e25 + 16) - 1e25
Quel est le résultat attendu ? Quel est le résultat obtenu ? Pourquoi ?
Solution page 485 C
Mettre le résultat ici (code et figure).
Exercice 217 On tape en Python les instructions suivantes.
>>> x = 1e200
>>> y X XX
>> z=y/y
[Il
Quelles sont les valeurs de y et z? Pourquoi ? Solution page 185 ©
Mettre le résultat ici (code et figure).
Exercice 218 On tape en Python les instructions suivantes.
>>> X 1e200
>DDY=EXEXX
>>> z=y/7y
Quelles sont les valeurs de y et z? Pourquoi ? Solution page 486 O
Mettre le résultat ici (code et figure).
Exercice 219 Ecrire un programme qui, partant du nombre 1,0, le divise
vingt fois de suite par 8, puis le multiplie vingt fois de suite par 3, puis enfin
affiche la valeur obtenue au final. Expliquer le résultat observé.260 Chapitre 20. Keprèésentation approximative des nombres reels
Mettre le résultat ici (code et figure).
Exercice 220 Nous allons écrire un programme qui estime la valeur de x de
la façon suivante, On répète un grand nombre de fois l'opération consistant
à choisir au hasard un point dans un carré de côté 1. On compte combien
de points tombent dans le quart de cercle de rayon 1 centré sur l'un des
coins du carré. Le rapport de ce nombre au nombre total de points donne
une estimation de 7/4. Pour tirer un nombre réel entre 0 et l, on utilise
uniform(0, 1), de la bibliothèque random. Solution page 486 D
Mettre le résultat ici (code et figure).
Exercice 221
1. Trouver un nombre (fottant l) x tel que x + 1 == x.
2. Trouver le plus petit tel nombre.
Indication : 1 s'agit d’une puissance de
Solution page 486 0
Mettre le résultat ici (code et figure).
Exercice 222
1. Trouver un nombre flottant x différent de O tel que
2.0 %* 100 + x == 2,0 *x 100.
2. Trouver un tel nombre aussi grand que possible, £ que T
Solution page 487 0
","title":"Exercice"},{"edit":"Mettre le résultat ici (code et figure).