DataManip Insights ÉPISODE 1Python : les pièges du débutantGratuit
🔢 Épisode 1 · Les nombres à virgule

« Python sait compter : 0,1 dix fois, ça fait 1. »
Non : 0,9999999999999999. Sur 10 000 additions de 0,1, 9 982 cumuls sont inexacts.

Python stocke les nombres à virgule en binaire (norme IEEE 754) : 0,1 n'a pas d'écriture exacte, il est remplacé par la valeur la plus proche. Une boucle qui ajoute dix fois 0,1 donne 0,9999999999999999 : l'erreur de 1,1 × 10⁻¹⁶ est minuscule, mais le test total == 1.0 renvoie False. Sur 10 000 additions, l'erreur monte à 1,6 × 10⁻¹⁰ et 9 982 des 10 000 cumuls sont inexacts. Ce n'est pas un défaut de Python : tous les langages qui utilisent des flottants font pareil.

🎯 L'analogie clé

Écrire 1/3 en décimal : 0,333… on s'arrête quelque part, et trois tiers ne font plus tout à fait 1.

Le principe

0,1 n'a pas d'écriture
binaire finie.

Un nombre à virgule Python (type float) occupe 64 bits. Comme 1/3 n'a pas d'écriture décimale finie, 0,1 n'a pas d'écriture binaire finie : Python garde la valeur représentable la plus proche. Chaque addition arrondit encore le résultat, et ces arrondis s'accumulent. Entre deux flottants voisins il y a un écart, l'ulp, qui grandit avec la valeur : 2,2 × 10⁻¹⁶ près de 1, 2 près de 10¹⁶.

🔢
Représentation
0,1 est stocké sous la forme du flottant le plus proche, pas exactement.
🧮
Arrondi cumulé
Chaque addition arrondit le résultat, et les erreurs s'additionnent.
⚖️
Comparaison
Comparer deux flottants avec == est fragile : on utilise une tolérance, math.isclose.
Le point clé : dix additions de 0,1 donnent 0,9999999999999999, avec 4 cumuls inexacts sur 10 ; sur 10 000 additions, 9 982 cumuls sont inexacts.
À vous de manipuler

Additionnez,
mesurez l'écart.

Réglez le nombre d'additions et la valeur ajoutée à chaque tour. La courbe donne l'erreur absolue du cumul après chaque addition, par rapport à la valeur exacte ; le point blanc est l'erreur après la dernière addition.

Erreur du cumul selon le nombre d'additions
Erreur absolue du cumul selon le nombre d'additions

Calcul avec les mêmes flottants 64 bits que Python ; la valeur exacte est (n × k) ÷ 100, calculée en une seule division.

Somme obtenue
-
ce que Python affiche
Erreur absolue
-
écart avec la valeur exacte
total == valeur exacte
-
le test d'égalité de Python
Cumuls inexacts
-
sur le nombre d'additions
À retenir : au réglage initial (10 fois 0,1), la somme est 0,9999999999999999, l'erreur de 1,1 × 10⁻¹⁶ et 4 cumuls sur 10 sont inexacts ; total == 1.0 vaut False.
Selon la taille des nombres

Plus le nombre est grand,
moins il a de précision.

La courbe donne l'écart entre deux flottants voisins (échelle logarithmique) selon la puissance de 10 du nombre. Près de 1 il vaut 2,2 × 10⁻¹⁶ ; près de 10⁶, 1,2 × 10⁻¹⁰ ; près de 10¹², 1,2 × 10⁻⁴ ; près de 10¹⁶, 2 : ajouter 1 à 2.0**53 ne change plus rien (float(2**53) + 1 == float(2**53) vaut True).

Écart entre flottants voisins
Écart entre deux flottants voisins selon la taille du nombre

Chips : écart (ulp) donné par math.ulp(10**k) ; les deux axes sont logarithmiques.

Autour de 1
-
écart entre deux flottants voisins
Autour de 10⁶
-
écart entre deux flottants voisins
Autour de 10¹²
-
écart entre deux flottants voisins
Autour de 10¹⁶
-
écart entre deux flottants voisins
Le point clé : l'écart entre deux flottants passe de 2,2 × 10⁻¹⁶ près de 1 à 2 près de 10¹⁶ : sur de très grands nombres, même des entiers consécutifs deviennent introuvables.
En pratique

Quatre réflexes
avec les décimaux.

Voici la démarche, puis un exemple.

⚖️
Ne comparez pas avec ==
Utilisez math.isclose(a, b), avec une tolérance.
💶
Comptez en centimes
Pour de l'argent, travaillez en entiers ou avec decimal.Decimal.
➕
Sommez prudemment
math.fsum limite l'accumulation d'erreurs ; sum() compense depuis Python 3.12, pas une boucle.
📏
Connaissez l'échelle
Au-delà de 2⁵³, un flottant ne représente plus tous les entiers.
Python · python_flottants.py
import math

total = 0.0
for _ in range(10):
    total += 0.1
total                                  # 0.9999999999999999
total == 1.0                           # False
math.isclose(total, 1.0)               # True : on compare avec une tolérance
float(2**53) + 1 == float(2**53)    # True : au-delà de 2**53, +1 disparaît
Test rapide

Vérifiez votre compréhension.

Une boucle ajoute dix fois 0.1 à un total qui démarre à 0. Que vaut total == 1.0 ?

Ce qu'il faut retenir

Épisode suivant

Sur 100 valeurs en ,5, l'arrondi à l'école ajoute 50 à la somme (5 050 au lieu de 5 000) quand round() reste exact ; mais round(v, 2) s'écarte de l'arrondi attendu pour 50 prix sur 100 finissant par 5

Puisque les nombres à virgule sont approchés, que fait round() quand une valeur tombe pile au milieu ? Python ne fait pas ce qu'on a appris à l'école.

ACCÈS COMPLET

Cet épisode est gratuit. Les 282 autres t'attendent.

Statistiques, finance quantitative, machine learning, deep learning, LLM, agents IA, MLOps : 321 épisodes avec des simulateurs à manipuler, pas des vidéos.

99 € (+ TVA selon le pays) · accès à vie · remboursement possible sous 7 jours
Débloquer les 282 épisodes · 99 € J'ai déjà une clé de licence
FULL ACCESS

This episode is free. The other 282 are waiting for you.

Statistics, quantitative finance, machine learning, deep learning, LLMs, AI agents, MLOps: 321 interactive episodes with simulators to play with, not videos.

€99 (+ VAT depending on country) · lifetime access · 7-day refund
Unlock the 282 episodes · €99 I already have a license key