Besoin d'aller plus loin qu'une simple addition ou multiplication ? Même si vous êtes comme moi et que les mathématiques vous donnent mal à la tête, vous allez voir que math vous simplifie la vie. Comme vous l'entendrez souvent, nul besoin de réinventer la roue, même pour des calculs complexes.
Dans ce guide, nous parlerons des fonctions principales de ce module.
Comment arrondir et tronquer des nombres avec Python ?
En Python, il existe plusieurs façons de réduire un nombre à virgule à un entier.
La fonction native round()
Sans même utiliser le module math, la fonction native round() permet d'arrondir à l'entier le plus proche.
Attention
round() arrondit les valeurs se terminant par .5 vers l'entier pair le plus proche (on parle alors d'arrondi bancaire).
print(round(2.4)) # Affiche : 2 print(round(2.6)) # Affiche : 3 print(round(2.5)) # Affiche : 2 (arrondi à l'entier pair) print(round(3.5)) # Affiche : 4 (arrondi à l'entier pair)
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
Arrondir vers le bas avec math.floor()
La fonction math.floor() renvoie le plus grand entier inférieur ou égal à la valeur donnée.
import math print(math.floor(3.9)) # Affiche : 3 print(math.floor(3.1)) # Affiche : 3
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
Arrondir vers le haut avec math.ceil()
Comme vous l'avez sans doute deviné, cette fonction est l'inverse de la précédente.
import math print(math.ceil(3.1)) # Affiche : 4 print(math.ceil(3.9)) # Affiche : 4
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
Tronquer les décimales avec math.trunc()
Avec math.trunc(), on ne parle plus d'arrondi : la fonction se charge de supprimer tout ce qui se trouve après la virgule.
import math print(math.trunc(3.9)) # Affiche : 3
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
Attention
Ne vous faites pas avoir par les nombres négatifs. C'est logique, mais je préfère revenir sur ce point :
-
math.floor()arrondit vers l'entier inférieur, donc plus loin de 0 -
math.ceil()arrondit vers l'entier supérieur, donc plus proche de 0
import math # Le plancher de -3.2 est l'entier en dessous print(math.floor(-3.2)) # Affiche : -4 # Le plafond de -3.2 est l'entier au-dessus print(math.ceil(-3.2)) # Affiche : -3
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
Calculer la valeur absolue en Python : abs() et math.fabs()
Pour obtenir la valeur positive d'un nombre, on utilise la valeur absolue. En Python, on peut utiliser abs(), une fonction native.
import math print(abs(-5)) # Affiche : 5 (entier) print(abs(-5.5)) # Affiche : 5.5 (flottant)
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
À noter
Vous remarquerez que abs() conserve le type d'origine du nombre converti.
math.fabs() convertit toujours le résultat en nombre à virgule.
import math print(math.fabs(-5)) # Affiche : 5.0 (toujours un flottant !)
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
Calculer des racines carrées et des puissances
Vous connaissez certainement l'opérateur ** pour les puissances. Le module math offre des fonctions dédiées.
La racine carrée avec math.sqrt()
Pour calculer la racine carrée d'un nombre, vous pouvez utiliser math.sqrt().
import math print(math.sqrt(16)) # Affiche : 4.0
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
La puissance d'un nombre avec math.pow()
La fonction math.pow(x, y) calcule x élevé à la puissance y. Contrairement à l'opérateur **, math.pow() renvoie toujours un nombre à virgule.
import math print(2 ** 3) # Affiche : 8 print(math.pow(2, 3)) # Affiche : 8.0
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
Les constantes mathématiques
Notez que le module math contient également quelques constantes.
import math print(math.pi) # Affiche : 3.141592653589793 print(math.e) # Affiche : 2.718281828459045 (Constante d'Euler) print(math.tau) # Affiche : 6.283185307179586 (Équivalent à 2 * Pi)
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
L'infini avec math.inf
Si vous aimez relever des petits défis ou exercices de code, math.inf peut s'avérer utile. Cette constante représente l'infini.
import math # Un défi classique : trouver le prix le plus bas manuellement # dans une liste avec des grands écarts de valeurs prix = [450, 1205, 99, 15, 2300, 8, 42, 10500, 350] # On initialise avec l'infini positif prix_minimum = math.inf for p in prix: if p < prix_minimum: prix_minimum = p print(f"Le prix le plus bas est : {prix_minimum}") # Affiche : 8
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
Une astuce pour ne pas initialiser une variable avec une valeur arbitraire comme 99999999999999 😅.
On pourrait très bien faire l'inverse :
import math # Un cas d'usage beaucoup plus logique pour l'infini négatif : # Trouver la température maximale en plein hiver temperatures = [-5, -12, -2, -18, -1, -7] # On initialise avec l'infini négatif temperature_max = -math.inf for t in temperatures: if t > temperature_max: temperature_max = t print(f"La température la plus élevée est : {temperature_max}") # Affiche : -1
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
La précision des flottants en Python : math.fsum() et decimal
Vous avez peut-être déjà remarqué que certains calculs avec des nombres à virgule donnaient des résultats un peu étranges.
print(0.1 + 0.1 + 0.1) # Affiche : 0.30000000000000004
Un calcul pourtant simple, mais un résultat erroné. Il s'agit d'un problème classique en informatique. En effet, comme les ordinateurs stockent les nombres en binaire, certaines fractions décimales très simples comme 0.1 ne peuvent pas être représentées de manière exacte. L'ordinateur stocke une approximation très proche de 0.1.
Le plus amusant dans tout ça, c'est que le problème se manifeste de deux façons bien distinctes.
L'imprécision de représentation
C'est ce que nous avons vu juste avant : 0.1 n'est pas exactement 0.1 en mémoire. Pour résoudre ce problème, sortons du cadre de math en parlant brièvement du module decimal.
from decimal import Decimal # On utilise des chaînes de caractères ('0.1') pour garantir # que la précision initiale soit parfaite dès la création du nombre print(Decimal('0.1') + Decimal('0.1') + Decimal('0.1')) # Affiche : 0.3 print(Decimal('0.3') - Decimal('0.1')) # Affiche : 0.2 # Sans les chaînes de caractères, la précision initiale peut être affectée print(Decimal(0.1) + Decimal(0.1) + Decimal(0.1)) # Affiche : 0.3000000000000000166533453694 print(Decimal(0.3) - Decimal(0.1)) # Affiche : 0.1999999999999999833466546306
À noter
Pour ceux qui connaissent Django, j'ai développé récemment une application qui nécessite des calculs précis. Django fournit un DecimalField via models, qui utilise en arrière-plan le module decimal.
L'accumulation des erreurs d'arrondi
Regardons un problème différent avec un autre cas, sans parler de decimal. Lorsque vous additionnez des flottants, les erreurs d'arrondi peuvent s'accumuler et se combiner.
import math # La somme totale devrait être 10000.0, car les 1e100 et -1e100 s'annulent, # laissant seulement les 1.0 à additionner. valeurs = [1e100, 1.0, -1e100] * 10_000 print(sum(valeurs)) # Affiche : 0.0 sur Python < 3.12 (résultat faux !) print(math.fsum(valeurs)) # Affiche : 10000.0 (résultat correct)
sum() perd la valeur de 1.0 à cause des très grands nombres qui l'entourent, alors que math.fsum() la préserve. Contrairement à sum(), cette fonction n'introduit aucune erreur d'arrondi supplémentaire pendant le calcul : elle travaille avec les imprécisions des flottants telles qu'elles sont, sans en ajouter de nouvelles.
Et pourquoi pas decimal ici aussi ? En fait, on parlait juste d'un problème différent. Decimal est conçu pour éviter l'imprécision dès la création des nombres. On pourrait donc éviter ce problème à la base avec Decimal, mais le but ici est de parler du comportement de sum() et fsum() avec des flottants à l'origine.
À noter
Depuis Python 3.12, sum() utilise un algorithme plus précis, mais la documentation recommande toujours d'utiliser math.fsum().
Documentation sum