Pourquoi 0.1 + 0.1 + 0.1 - 0.3
évalue à 5.5511151231257827e-17
en Python?Numéros de base en Python!
Répondre
Parce que c'est ainsi que fonctionnent les nombres à virgule flottante. Si vous voulez des chiffres précis, utilisez le module decimal
. Si vous souhaitez utiliser des nombres à virgule flottante, vous devez vous souvenir de les arrondir à une précision spécifique lorsque vous les affichez.
>>> print '%.2f' % (0.1+0.1+0.1-0.3,)
0.00
Exactement ... et puisque les autres nombres ont seulement été spécifiés à 1 décimale, vous ne pouvez pas sérieusement vous attendre à afficher 17 décimales dans la réponse. – pavium
Plus précisément, c'est ainsi que fonctionnent les nombres à virgule flottante * binaire *. Les nombres représentés par le type Decimal en Python sont des nombres décimaux à virgule flottante. –
Oui, je pourrais être plus clair. Par "nombres à virgule flottante", je voulais dire le type "float" en Python. –
En raison de la manière dont les nombres de points sont représentés dans Floating un ordinateur. Ce n'est pas juste une chose Python.
[Citation] classe Flt {\t public static void main (String args []) { \t \t \t flotteur w, x, y, z, ans; \t \t w = 0,1f; \t \t x = w; \t \t y = w; \t \t z = 0,3f; \t \t ans = w + x + y-z; \t \t System.out.println (ans); \t}} [/ citation] en Java 0.0 donne –
'Parce que System.out.println' arrondit le nombre, ce qui est exactement ce que le code Python dans ma réponse ne. –
Ceci est un problème avec les nombres à virgule flottante en général. Voir this section sur Wikipedia pour une description. Grosso modo, il y a des erreurs d'arrondi. Notez que le nombre que vous nous avez donné était très petit - environ 0,00000000000000005551115123. Voici a more technical paper sur le sujet.
La réponse est ici: What Every Computer Scientist Should Know About Floating-Point Arithmetic
À titre d'exemple, considérons représentant un tiers comme un nombre scientifique dans la base 10., vous aurez le vent Avec seulement un nombre fini de chiffres (disons, 10) avec une erreur d'arrondi. Dites 1/3 ≈ 0,3333333333e0. Alors 1/3 + 1/3 + 1/3 (après la première conversion en expansions décimales) est représenté par 0,9999999999e0, mais 1 est 1,0e0. De même, 1/7 ≈ 0.1428571429e0, et 1/7 + 1/7 serait 0.2857142858e0, mais la représentation pour 2/7 serait 0.2857142857e0. Dans les deux cas, la somme est désactivée de 1e-10.
Vous pourriez être intéressé de savoir que Python 3 a amélioré la situation en changeant le fonctionnement de repr
. Il vous donne maintenant la plus courte représentation de chaîne qui sera reconvertie au flotteur d'origine:
Python 3.1.1+ (r311:74480, Oct 11 2009, 20:19:13) [GCC 4.3.4] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 0.1 '0.1'
Les anciennes versions se comportent comme ceci:
Python 2.6.4 (r264:75706, Oct 28 2009, 22:19:17) [GCC 4.3.4] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 0.1 '0.10000000000000001'
Il est seulement la sortie de repr
(appelé implicitement lorsque vous entrez une valeur dans l'interpréteur interactif) qui a changé. Les valeurs sous-jacentes sont encore IEEE-754 nombres à virgule flottante, et ils ont encore les limites habituelles:
Python 3.1.1+ (r311:74480, Oct 11 2009, 20:19:13) [GCC 4.3.4] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 0.1 0.1 >>> 0.2 0.2 >>> 0.3 0.3 >>> 0.1 + 0.2 0.30000000000000004 >>> 0.1 + 0.2 - 0.3 5.551115123125783e-17
accord de précision wil varient ... mais ici 5.5511151231257827e-17 est incorrect !! –
Tout en ne voulant rien enlever des réponses ci-dessous, 5.55e-17 est vraiment une * petite * quantité et serait considérée comme nulle dans la plupart des situations pratiques. – pavium
Si vous ne comprenez pas la notation, le nombre que vous voyez signifie 0.000000000000000055511151231257827. Très petit. – Artelius