Ce qui suit explique comment arrondir des nombres en Python en les arrondissant ou en les arrondissant à un nombre pair. Les nombres sont supposés être de type flottant (float) ou entier (int).
- fonction intégrée (par exemple, dans un langage de programmation):
round()
- Arrondissez les décimales à n'importe quel nombre de chiffres.
- Arrondir les nombres entiers à un nombre quelconque de chiffres.
- round() arrondit à un nombre pair, pas à un arrondi commun
- bibliothèque standard
decimal
quantize()
Decimal
Création d'un objet- Arrondi des décimales à un nombre quelconque de chiffres et arrondi aux nombres pairs
- Arrondi des nombres entiers à un nombre quelconque de chiffres et arrondi aux nombres pairs
- Définir une nouvelle fonction
- Arrondissez les décimales à n'importe quel nombre de chiffres.
- Arrondir les nombres entiers à n'importe quel nombre de chiffres
- Note : Pour les valeurs négatives
Notez que, comme mentionné ci-dessus, la fonction intégrée round n'est pas un arrondi général, mais un arrondi à un nombre pair. Voir ci-dessous pour plus de détails.
fonction intégrée (par exemple, dans un langage de programmation): round()
Round() est fournie comme une fonction intégrée. Elle peut être utilisée sans importer de module.
Le premier argument est le nombre original, et le second est le nombre de chiffres (le nombre de chiffres à arrondir).
Arrondissez les décimales à n'importe quel nombre de chiffres.
Voici un exemple de traitement pour le type float à virgule flottante.
Si le deuxième argument est omis, il est arrondi à un nombre entier. Le type devient également un type integer int.
f = 123.456 print(round(f)) # 123 print(type(round(f))) # <class 'int'>
Si le second argument est spécifié, il renvoie un type de flottant.
Si un nombre entier positif est spécifié, la place décimale est spécifiée ; si un nombre entier négatif est spécifié, la place entière est spécifiée. -1 arrondit au dixième le plus proche, -2 arrondit au centième le plus proche, et 0 arrondit à un entier (la première place), mais renvoie un type flottant, contrairement à ce qui se passe lorsqu'il est omis.
print(round(f, 1)) # 123.5 print(round(f, 2)) # 123.46 print(round(f, -1)) # 120.0 print(round(f, -2)) # 100.0 print(round(f, 0)) # 123.0 print(type(round(f, 0))) # <class 'float'>
Arrondir les nombres entiers à un nombre quelconque de chiffres.
Voici un exemple de traitement pour le type integer int.
Si le deuxième argument est omis, ou si 0 ou un nombre entier positif est spécifié, la valeur originale est retournée telle quelle. Si un nombre entier négatif est spécifié, il est arrondi au chiffre entier correspondant. Dans les deux cas, un entier de type int est retourné.
i = 99518 print(round(i)) # 99518 print(round(i, 2)) # 99518 print(round(i, -1)) # 99520 print(round(i, -2)) # 99500 print(round(i, -3)) # 100000
round() arrondit à un nombre pair, pas à un arrondi commun
Notez que l'arrondi avec la fonction intégrée round() dans Python 3 arrondit à un nombre pair, et non à un arrondi général.
Comme indiqué dans la documentation officielle, 0,5 est arrondi à 0, 5 est arrondi à 0, et ainsi de suite.
print('0.4 =>', round(0.4)) print('0.5 =>', round(0.5)) print('0.6 =>', round(0.6)) # 0.4 => 0 # 0.5 => 0 # 0.6 => 1 print('4 =>', round(4, -1)) print('5 =>', round(5, -1)) print('6 =>', round(6, -1)) # 4 => 0 # 5 => 0 # 6 => 10
La définition de l'arrondi à un nombre pair est la suivante.
Si la fraction est inférieure à 0,5, arrondissez-la au chiffre inférieur ; si la fraction est supérieure à 0,5, arrondissez-la au chiffre supérieur ; si la fraction est exactement 0,5, arrondissez-la au chiffre pair entre l'arrondi au chiffre inférieur et l'arrondi au chiffre supérieur.
Rounding – Wikipedia
0,5 n'est pas toujours tronqué.
print('0.5 =>', round(0.5)) print('1.5 =>', round(1.5)) print('2.5 =>', round(2.5)) print('3.5 =>', round(3.5)) print('4.5 =>', round(4.5)) # 0.5 => 0 # 1.5 => 2 # 2.5 => 2 # 3.5 => 4 # 4.5 => 4
Dans certains cas, la définition de l'arrondi à un nombre pair ne s'applique même pas au traitement après deux décimales.
print('0.05 =>', round(0.05, 1)) print('0.15 =>', round(0.15, 1)) print('0.25 =>', round(0.25, 1)) print('0.35 =>', round(0.35, 1)) print('0.45 =>', round(0.45, 1)) # 0.05 => 0.1 # 0.15 => 0.1 # 0.25 => 0.2 # 0.35 => 0.3 # 0.45 => 0.5
Cela est dû au fait que les décimales ne peuvent pas être représentées exactement comme des nombres à virgule flottante, comme indiqué dans la documentation officielle.
Le comportement de round() pour les nombres à virgule flottante peut vous surprendre.:Par exemple, round(2.675, 2) vous donnera 2.67 au lieu de 2.68 comme prévu. Il ne s'agit pas d'un bogue.:Ceci est dû au fait que la plupart des décimales ne peuvent pas être représentées exactement par des nombres à virgule flottante.
round() — Built-in Functions — Python 3.10.2 Documentation
Si vous souhaitez obtenir un arrondi général ou un arrondi précis des décimales aux nombres pairs, vous pouvez utiliser la bibliothèque standard decimal quantize (décrite ci-dessous) ou définir une nouvelle fonction.
Notez également que round() dans Python 2 n'est pas un arrondi à un nombre pair, mais un arrondi.
quantize() de la bibliothèque standard décimale
Le module décimal de la bibliothèque standard peut être utilisé pour manipuler des nombres décimaux exacts à virgule flottante.
En utilisant la méthode quantize() du module décimal, il est possible d'arrondir les nombres en spécifiant le mode d'arrondi.
- decimal quantize() — Decimal fixed point and floating point arithmetic — Python 3.10.2 Documentation
- Rounding modes — Decimal fixed point and floating point arithmetic — Python 3.10.2 Documentation
Les valeurs définies pour l'arrondi de l'argument de la méthode quantize() ont les significations suivantes, respectivement.
ROUND_HALF_UP
:Arrondi généralROUND_HALF_EVEN
:Arrondir aux nombres pairs
Le module decimal est une bibliothèque standard, donc aucune installation supplémentaire n'est requise, mais l'importation est nécessaire.
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
Création d'un objet Décimal
Decimal() peut être utilisé pour créer des objets de type Decimal.
Si vous spécifiez un type de flottant comme argument, vous pouvez voir comment la valeur est réellement traitée.
print(Decimal(0.05)) # 0.05000000000000000277555756156289135105907917022705078125 print(type(Decimal(0.05))) # <class 'decimal.Decimal'>
Comme le montre l'exemple, 0,05 n'est pas traité comme exactement 0,05. C'est la raison pour laquelle la fonction intégrée round() décrite ci-dessus arrondit à une valeur différente de celle attendue pour les valeurs décimales incluant 0,05 dans l'exemple.
Comme 0,5 est la moitié (-1 puissance de 2), il peut être exprimé exactement en notation binaire.
print(Decimal(0.5)) # 0.5
Si vous spécifiez le type de chaîne str au lieu du type float, il sera traité comme le type Decimal de la valeur exacte.
print(Decimal('0.05')) # 0.05
Arrondi des décimales à un nombre quelconque de chiffres et arrondi aux nombres pairs
Appelez quantize() à partir d'un objet de type Decimal pour arrondir la valeur.
Le premier argument de quantize() est une chaîne de caractères avec le même nombre de chiffres que le nombre de chiffres que vous voulez trouver, comme '0.1' ou '0.01'.
De plus, l'argument ROUNDING spécifie le mode d'arrondi ; si ROUND_HALF_UP est spécifié, l'arrondi général est utilisé.
f = 123.456 print(Decimal(str(f)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) # 123 print(Decimal(str(f)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP)) # 123.5 print(Decimal(str(f)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 123.46
Contrairement à la fonction intégrée round(), 0,5 est arrondi à 1.
print('0.4 =>', Decimal(str(0.4)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) print('0.5 =>', Decimal(str(0.5)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) print('0.6 =>', Decimal(str(0.6)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) # 0.4 => 0 # 0.5 => 1 # 0.6 => 1
Si l'argument rounding est défini sur ROUND_HALF_EVEN, l'arrondi est effectué sur les nombres pairs comme dans la fonction intégrée round().
Comme mentionné ci-dessus, si un type de flottant est spécifié comme argument de Decimal(), il est traité comme un objet Decimal avec une valeur égale à la valeur réelle du type de flottant, donc le résultat de l'utilisation de la méthode quantize() sera différent de ce qui est attendu, tout comme la fonction intégrée round().
print('0.05 =>', round(0.05, 1)) print('0.15 =>', round(0.15, 1)) print('0.25 =>', round(0.25, 1)) print('0.35 =>', round(0.35, 1)) print('0.45 =>', round(0.45, 1)) # 0.05 => 0.1 # 0.15 => 0.1 # 0.25 => 0.2 # 0.35 => 0.3 # 0.45 => 0.5 print('0.05 =>', Decimal(0.05).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.15 =>', Decimal(0.15).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.25 =>', Decimal(0.25).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.35 =>', Decimal(0.35).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.45 =>', Decimal(0.45).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) # 0.05 => 0.1 # 0.15 => 0.1 # 0.25 => 0.2 # 0.35 => 0.3 # 0.45 => 0.5
Si l'argument de Decimal() est spécifié comme une chaîne de caractères de type str, il est traité comme un objet Decimal ayant exactement cette valeur, et le résultat est donc conforme aux attentes.
print('0.05 =>', Decimal(str(0.05)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.15 =>', Decimal(str(0.15)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.25 =>', Decimal(str(0.25)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.35 =>', Decimal(str(0.35)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.45 =>', Decimal(str(0.45)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) # 0.05 => 0.0 # 0.15 => 0.2 # 0.25 => 0.2 # 0.35 => 0.4 # 0.45 => 0.4
Étant donné que 0,5 peut être correctement traité par le type float, il n'y a aucun problème à spécifier le type float comme argument de Decimal() lors de l'arrondi à un entier, mais il est plus sûr de spécifier le type string str lors de l'arrondi à une décimale.
Par exemple, 2,675 est en fait 2,67499…. dans le type float. Par conséquent, si vous voulez arrondir à deux décimales, vous devez spécifier une chaîne de caractères à Decimal(), sinon le résultat sera différent du résultat attendu, que vous arrondissiez au nombre entier le plus proche (ROUND_HALF_UP) ou à un nombre pair (ROUND_HALF_EVEN).
print(Decimal(2.675)) # 2.67499999999999982236431605997495353221893310546875 print(Decimal(2.675).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 2.67 print(Decimal(str(2.675)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 2.68 print(Decimal(2.675).quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)) # 2.67 print(Decimal(str(2.675)).quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)) # 2.68
Notez que la méthode quantize() renvoie un nombre de type décimal, donc si vous voulez opérer sur un nombre de type flottant, vous devez le convertir en type flottant en utilisant float(), sinon une erreur se produira.
d = Decimal('123.456').quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) print(d) # 123.46 print(type(d)) # <class 'decimal.Decimal'> # print(1.2 + d) # TypeError: unsupported operand type(s) for +: 'float' and 'decimal.Decimal' print(1.2 + float(d)) # 124.66
Arrondi des nombres entiers à un nombre quelconque de chiffres et arrondi aux nombres pairs
Si vous voulez arrondir à un chiffre entier, spécifier quelque chose comme '10' comme premier argument ne vous donnera pas le résultat souhaité.
i = 99518 print(Decimal(i).quantize(Decimal('10'), rounding=ROUND_HALF_UP)) # 99518
C'est parce que quantize() effectue l'arrondi en fonction de l'exposant de l'objet Decimal, mais l'exposant de Decimal('10') est 0, et non 1.
Vous pouvez spécifier un exposant arbitraire en utilisant E comme chaîne d'exposant (par exemple, '1E1'). L'exposant peut être vérifié dans la méthode as_tuple.
print(Decimal('10').as_tuple()) # DecimalTuple(sign=0, digits=(1, 0), exponent=0) print(Decimal('1E1').as_tuple()) # DecimalTuple(sign=0, digits=(1,), exponent=1)
Comme c'est le cas, le résultat sera en notation exponentielle en utilisant E. Si vous voulez utiliser la notation normale, ou si vous voulez opérer avec le type entier int après l'arrondi, utilisez int() pour convertir le résultat.
print(Decimal(i).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP)) # 9.952E+4 print(int(Decimal(i).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) # 99520 print(int(Decimal(i).quantize(Decimal('1E2'), rounding=ROUND_HALF_UP))) # 99500 print(int(Decimal(i).quantize(Decimal('1E3'), rounding=ROUND_HALF_UP))) # 100000
Si l'argument rounding est défini sur ROUND_HALF_UP, un arrondi général sera effectué, par exemple, 5 sera arrondi à 10.
print('4 =>', int(Decimal(4).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) print('5 =>', int(Decimal(5).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) print('6 =>', int(Decimal(6).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) # 4 => 0 # 5 => 10 # 6 => 10
Bien entendu, il n'y a aucun problème si vous le spécifiez sous forme de chaîne de caractères.
Définir une nouvelle fonction
La méthode qui consiste à utiliser le module décimal est précise et sûre, mais si vous n'êtes pas à l'aise avec la conversion de type, vous pouvez définir une nouvelle fonction pour réaliser un arrondi général.
Il existe de nombreuses façons de procéder, par exemple, la fonction suivante.
def my_round(val, digit=0): p = 10 ** digit return (val * p * 2 + 1) // 2 / p
Si vous n'avez pas besoin de préciser le nombre de chiffres et que vous arrondissez toujours à la première décimale, vous pouvez utiliser une forme plus simple.
my_round_int = lambda x: int((x * 2 + 1) // 2)
Si vous devez être précis, il est plus sûr d'utiliser les décimales.
Les informations suivantes sont données à titre indicatif.
Arrondissez les décimales à n'importe quel nombre de chiffres.
print(int(my_round(f))) # 123 print(my_round_int(f)) # 123 print(my_round(f, 1)) # 123.5 print(my_round(f, 2)) # 123.46
Contrairement à l'arrondi, 0,5 devient 1 selon l'arrondi général.
print(int(my_round(0.4))) print(int(my_round(0.5))) print(int(my_round(0.6))) # 0 # 1 # 1
Arrondir les nombres entiers à n'importe quel nombre de chiffres
i = 99518 print(int(my_round(i, -1))) # 99520 print(int(my_round(i, -2))) # 99500 print(int(my_round(i, -3))) # 100000
Contrairement à l'arrondi, 5 devient 10 selon l'arrondi courant.
print(int(my_round(4, -1))) print(int(my_round(5, -1))) print(int(my_round(6, -1))) # 0 # 10 # 10
Note : Pour les valeurs négatives
Dans l'exemple de fonction ci-dessus, -0,5 est arrondi à 0.
print(int(my_round(-0.4))) print(int(my_round(-0.5))) print(int(my_round(-0.6))) # 0 # 0 # -1
Il existe plusieurs façons d'envisager l'arrondi pour les valeurs négatives, mais si vous voulez transformer -0,5 en -1, vous pouvez le modifier comme suit, par exemple
import math def my_round2(val, digit=0): p = 10 ** digit s = math.copysign(1, val) return (s * val * p * 2 + 1) // 2 / p * s print(int(my_round2(-0.4))) print(int(my_round2(-0.5))) print(int(my_round2(-0.6))) # 0 # -1 # -1