0.1 + 0.2Ce n'est pas un bogue de Python : c'est une réalité de tous les ordinateurs. Les nombres réels sont rangés de façon approximative, et ces minuscules écarts ont de vraies conséquences en calcul scientifique. Voyons pourquoi - et comment s'en protéger.
Un ordinateur n'a qu'un nombre fini de bits (64) pour ranger un réel. Comme 1/3 qu'on ne peut pas écrire exactement en décimal, beaucoup de nombres - même 0,1 ! - sont infinis en binaire. L'ordinateur les coupe et garde une valeur très proche, mais pas exacte.
| Type | De ... à ... | Précision / piège |
|---|---|---|
| int (Python) | illimité 🎉 | grandit tout seul (big int natif) |
| float (Python) | jusqu'à ±1.8e308 | ~15-16 chiffres ; au-delà → inf |
| float (minuscule) | jusqu'à 5e-324 | en dessous → 0.0 (disparaît) |
| numpy int64 | ±9.2e18 | ⚠ déborde en silence |
Bonne nouvelle : en Python pur, les entiers sont illimités. Mais le float a des bornes, et dès qu'on passe à numpy (omniprésent en sciences), les entiers redeviennent bornés et peuvent déborder sans prévenir. Toujours savoir dans quel intervalle on travaille.
.sum() garde le type, .mean() donne un float.sum() → même type.mean() → toujours floatSur un tableau numpy, .mean() fait une vraie division et renvoie toujours un float. Mais .sum() conserve le type du tableau : des entiers donnent un entier (un int64 qui peut déborder, cf. slide précédente), des flottants donnent un flottant. Pour une grosse somme d'entiers sûre, on convertit d'abord (ages.astype(float)) ou on reste en int Python.
==En sciences, deux réels sont « égaux » s'ils sont assez proches. math.isclose(a, b) compare avec une tolérance ; sinon on teste soi-même abs(a - b) < 1e-9. Le == strict reste réservé aux entiers.
Chaque opération ajoute une miette d'erreur. Dans une boucle de simulation (une trajectoire calculée pas à pas, comme la chute de S3.1), ces miettes s'additionnent et le résultat dérive. math.fsum() fait une somme compensée bien plus précise qu'une addition naïve.
À très grande échelle, l'écart entre deux réels voisins dépasse 1 : ajouter 1 à 1e16 ne change rien. Soustraire ensuite deux nombres presque égaux ne laisse que de l'erreur - on appelle ça la cancellation catastrophique. En astronomie (différence de deux grandes distances), on réorganise la formule pour l'éviter.
inf et nan : les valeurs fantômesinf apparaît quand un résultat dépasse la borne ; nan (« not a number ») quand il est indéfini (inf - inf, 0/0). Piège célèbre : nan n'est égal à rien, pas même à lui-même. On les détecte avec math.isnan() et math.isinf().
On arrondit pour montrer un résultat, jamais au milieu d'un calcul : arrondir trop tôt jette de la précision qu'on ne récupère plus. round() renvoie un nombre, f"{x:.2f}" renvoie un texte mis en forme. Garde toujours la valeur complète pour les étapes suivantes.
float ne suffit pasDecimal calcule en base 10 comme nous (idéal pour l'argent ou des mesures à décimales exactes) ; Fraction garde les nombres sous forme de fractions exactes (1/3 reste 1/3, zéro erreur). Plus lents que float, mais exacts.
mpmathLe float plafonne PI à ~15 décimales. Pour aller plus loin (les « big réels »), mpmath calcule avec autant de chiffres qu'on veut : on règle mp.dps et on obtient PI à 50, 100, 1000 décimales. L'outil du calcul scientifique de haute précision.
Pas besoin de module pour les big int en Python : un entier grandit indéfiniment (factorielles géantes, cryptographie...). Le danger vient de numpy, dont les int64 ont une borne : pour de très grands comptes, on reste en entier Python (ou dtype=object).
| Le piège | Le réflexe |
|---|---|
| Comparer deux réels | math.isclose(a, b) |
| Sommer beaucoup de réels | math.fsum(liste) |
| Afficher un résultat | round(x, 2) / f"{x:.2f}" |
| Argent, décimales exactes | Decimal / Fraction |
| Très haute précision (PI...) | mpmath (mp.dps) |
| Très grands entiers | int Python (pas numpy) |
Le réel parfait n'existe pas dans la machine - mais avec ces réflexes, tes calculs restent justes et honnêtes. Le fond technique complet (IEEE 754, epsilon machine) t'attend dans l'En savoir plus.