Des calculs déroutants☘
Au problème du nombre fini de chiffres s'ajoute le problème de la représentation des nombres décimaux en base 2. Cela donne des résultats dont il faut apprendre à se méfier...
Exemple
-
Tout d'abord, calculons
0.1 + 0.1
:En demandant à Python, si, pour lui,>>> 0.1 + 0.1 0.2 >>> 0.1 + 0.1 == 0.2 True
0.1 + 0.1
est bien égal à0.2
, tout semble bien se passer. -
A présent, calculons
0.1 + 0.1 + 0.1
:Étonnant, il semble que le résultat ne soit pas>>> 0.1 + 0.1 + 0.1 0.30000000000000004
0.3
! -
Demandons alors à Python si
0.1 + 0.1 + 0.1
est bien égal à0.3
:Étonnant n'est-ce pas ?>>> 0.1 + 0.1 + 0.1 == 0.3 False
-
De même :
Python répond FAUX !>>> 0.1 + 0.2 == 0.3 False
Important
Cela n'est pas lié au langage Python. On retrouvera ce problème dans
tous les langages de programmation.
Ce problème est dû à la façon dont les nombres à virgule sont codés en
machine.
A retenir
On ne doit jamais tester l'égalité de deux flottants avec le comparateur
« ==
».
Il faudra se rappeler de l'exemple du calcul de 0.1 + 0.1 + 0.1
ci-dessus.
Si l'on cherche à tester l'égalité de flottants en machine, on ne teste que
leur proximité (avec risques d'erreur donc).
Le module math
de Python propose une fonction spécifique pour ce type de
test : isclose().
>>> from math import isclose
>>> isclose(0.1 + 0.2, 0.3)
True
Exemple☘
La fonction fractions_egales()
a pour paramètres les entiers a
, b
, c
et d
. Cette fonction renvoie True
si la fraction \frac{a}{b} est égale
à la fraction \frac{c}{d} et False
sinon.
-
Quelle précondition sur les paramètres semble-t-il raisonnable d'imposer ?
Une réponse
Les paramètres
b
etd
, qui représentent les dénominateurs, doivent être non nuls. -
Complétez le code de la fonction en ajoutant une assertion pour traduire la précondition précédente.
1 2 3 4 5 6
def fractions_egales(a, b, c, d): """ a, b, c, d – int, entiers avec b et d non nuls Sortie: bool – True lorsque la fraction a/b est égale à c/d, False sinon """
Attention
Le test
if a/b == c/d
serait une bien mauvaise idée.
Rappelez-vous : on ne peut pas vérifier l'égalité de deux flottants avec «==
» !Une solution
1 2 3 4 5 6 7 8
def fractions_egales(a, b, c, d): """ a, b, c, d – int, entiers avec b et d non nuls Sortie: bool – True lorsque est égale à , False sinon """ assert (b!= 0) and (d!= 0), "dénominateur nul !" return a*d == b*c
Des règles de calcul étonnantes☘
Info
Soient a, b et c des nombres réels. On a : (a+b)+c = a+(b+c).
C'est ce que l'on appelle associativité de l'addition de nombres réels (le mot « associativité » est utilisé pour rappeler que l'on peut, pour additionner, « associer » les deux premiers ou « associer » les deux derniers).
En machine, l'addition des flottants n'est pas associative :
>>> (0.3 + 0.9) + 0.2
1.4
>>> 0.3 + (0.9 + 0.2)
1.4000000000000001
>>> (0.3 + 0.9) + 0.2 == 0.3 + (0.9 + 0.2)
False
L'essentiel des calculs en machine sur les flottants ne sont donc que des calculs de valeurs approchées.
On insiste donc, une fois de plus, sur la non-utilisation de « ==
» entre
flottants : l'information obtenue avec un test a == b
(où a
et b
sont
de type float
) ne concerne que les flottants et donne rarement une
information sur les nombres mathématiques qu'ils sont censés représenter.