Python, comme de nombreux autres langages ainsi que des implémentations matérielles, suit la norme IEEE 754 pour manipuler les nombres à virgule (le type float
en Python). Cette norme définit les tailles possibles de mémoire allouée pour contenir le nombre. La taille étant fixe, certains nombres ne sont pas représentables et la valeur enregistrée peut être légèrement erronée.
Cette situation n’est donc pas spécifique à Python. L’écart entre la valeur saisie et la valeur en mémoire est visible avec un interpréteur Python :
$ python3 -q >>> 1.9999999999999943e+71 1.9999999999999942e+71
ou un calcul qui devrait valoir 0
si les mathématiques étaient une science exacte :
$ python3 -q >>> 0.1 + 0.1 + 0.1 - 0.3 5.551115123125783e-17
Ce type d’erreur ne se rencontre pas uniquement dans les domaines spatial ou scientifique. Par exemple, des calculs de TVA et TTC peuvent produire des erreurs visibles pour l’utilisateur.
Pour éviter ces erreurs, il est possible d’utiliser la bibliothèque decimal incluse dans la bibliothèque standard :
$ python3 -q >>> from decimal import Decimal >>> decimal.Decimal('1.9999999999999943e+71') Decimal('1.9999999999999943E+71') >>> Decimal(1) / Decimal(10) + \ ... Decimal(1) / Decimal(10) + \ ... Decimal(1) / Decimal(10) - \ ... Decimal(3) / Decimal(10) Decimal('0.0')
Un autre moyen est de faire des calculs en n’utilisant que des entiers et faire des conversions au dernier moment. Dans le cas de la TVA, cela signifie de ne travailler qu’en centimes et de ne convertir en euro que lors de l’affichage à l’utilisateur (avec l’arrondi adapté, limité à deux décimales).
Références
- pour plus de détails sur IEEE 754, la page wikipedia francophone
- l’exemple de calcul provient de la documentation du module
decimal
- l’article ayant inspiré cet article