web-dev-qa-db-fra.com

Arrondir à la deuxième décimale dans Python

Comment puis-je arrondir un nombre à la deuxième décimale en python? Par exemple:

0.022499999999999999

Doit arrondir à 0.03

0.1111111111111000

Doit arrondir à 0.12

S'il y a une valeur dans la troisième décimale, je veux qu'elle arrondisse toujours en me laissant 2 valeurs derrière la virgule.

43
user1202589

Python inclut la fonction round() qui vous permet de spécifier le nombre de chiffres souhaité. De la documentation:

round(x[, n])

Renvoie la valeur en virgule flottante x arrondie à n chiffres après le point décimal. Si n est omis, la valeur par défaut est zéro. Le résultat est un nombre à virgule flottante. Les valeurs sont arrondies au multiple le plus proche de 10 à la puissance moins n; si deux multiples sont également proches l'un de l'autre, l'arrondi est fait à partir de 0 (par exemple, arrondi (0.5) vaut 1.0 et arrondi (-0.5) vaut -1.0).

Donc, vous voudriez utiliser round(x, 2) pour arrondir normalement. Pour vous assurer que le nombre est toujours arrondi , vous devez utiliser la fonction ceil(x). De même, pour arrondir vers le bas , utilisez floor(x).

48
simchona
from math import ceil

num = 0.1111111111000
num = ceil(num * 100) / 100.0

Voir:
math.ceil documentation
round documentation - Vous voudrez probablement le vérifier quand même pour référence future

26
Edwin

Extrapolant à partir de la réponse d'Edwin:

from math import ceil, floor
def float_round(num, places = 0, direction = floor):
    return direction(num * (10**places)) / float(10**places)

Utiliser:

>>> float_round(0.21111, 3, ceil)  #round up
>>> 0.212
>>> float_round(0.21111, 3)        #round down
>>> 0.211
>>> float_round(0.21111, 3, round) #round naturally
>>> 0.211
13
Patrick Perini
x = math.ceil(x * 100.0) / 100.0
11
Mark Ransom

Cela dépend du comportement que vous voulez lorsque vous considérez des nombres positifs et négatifs, mais si vous voulez quelque chose qui arrondit toujours à une valeur plus grande (par exemple, 2.0449 -> 2.05, -2.0449 -> -2.04), vous pouvez alors:

round(x + 0.005, 2)

ou un petit amateur:

def round_up(x, place):
    return round(x + 5 * 10**(-1 * (place + 1)), place)

Cela semble aussi fonctionner comme suit:

round(144, -1)
# 140
round_up(144, -1)
# 150
round_up(1e308, -307)
# 1.1e308
10
ajp619

Notez que l'astuce ceil(num * 100) / 100 plantera certaines entrées dégénérées, comme 1e308. Cela peut ne pas arriver souvent, mais je peux vous dire que cela ne m'a coûté que quelques jours. Pour éviter cela, "ça serait bien si" ceil() et floor() prenaient un argument de décimales, comme (round() fait ... Pendant ce temps, Quelqu'un connaît-il une alternative propre qui ne plantera pas sur des entrées de ce type? J'avais quelques espoirs pour le paquet decimal mais il semble mourir aussi:

>>> from math import ceil
>>> from decimal import Decimal, ROUND_DOWN, ROUND_UP
>>> num = 0.1111111111000
>>> ceil(num * 100) / 100
0.12
>>> float(Decimal(num).quantize(Decimal('.01'), rounding=ROUND_UP))
0.12
>>> num = 1e308
>>> ceil(num * 100) / 100
Traceback (most recent call last):
  File "<string>", line 301, in runcode
  File "<interactive input>", line 1, in <module>
OverflowError: cannot convert float infinity to integer
>>> float(Decimal(num).quantize(Decimal('.01'), rounding=ROUND_UP))
Traceback (most recent call last):
  File "<string>", line 301, in runcode
  File "<interactive input>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

Bien sûr, on pourrait dire que planter est le seul comportement sain sur de telles entrées, mais je dirais que ce n’est pas l’arrondi, mais la multiplication qui cause le problème (c’est pourquoi, par exemple, 1e306 ne plante pas), et une mise en œuvre plus propre de la ronde de la n-place fn éviterait le hack de la multiplication.

4
Jacob Eliosoff
def round_up(number, ndigits=None):
    # start by just rounding the number, as sometimes this rounds it up
    result = round(number, ndigits if ndigits else 0)
    if result < number:
        # whoops, the number was rounded down instead, so correct for that
        if ndigits:
            # use the type of number provided, e.g. float, decimal, fraction
            Numerical = type(number)
            # add the digit 1 in the correct decimal place
            result += Numerical(10) ** -ndigits
            # may need to be tweaked slightly if the addition was inexact
            result = round(result, ndigits)
        else:
            result += 1 # same as 10 ** -0 for precision of zero digits
    return result

assert round_up(0.022499999999999999, 2) == 0.03
assert round_up(0.1111111111111000, 2) == 0.12

assert round_up(1.11, 2) == 1.11
assert round_up(1e308, 2) == 1e308
2

La fonction python round pourrait arrondir ce qui ne vous attend pas.

Vous pouvez être plus précis sur la méthode d'arrondi en utilisant Decimal.quantize

par exemple.

from decimal import Decimal, ROUND_HALF_UP
res = Decimal('0.25').quantize(Decimal('0.0'), rounding=ROUND_HALF_UP)
print(res) 
# prints 0.3

Plus de référence:

https://Gist.github.com/jackiekazil/6201722

0
James Lin

La fonction ronde indiquée ne fonctionne pas pour les entiers définis tels que:

a = 8
tour (a, 3)
8.0
a = 8.00
tour (a, 3)
8.0
a = 8.000000000000000000000000
tour (a, 3)
8.0

mais, travaille pour:

r = 400/3,0
r
133.33333333333334
round (r, 3)
133.333

De plus, les décimales telles que 2,675 sont arrondies à 2,67 et non 2,68.
Mieux vaut utiliser l’autre méthode décrite ci-dessus.

0
Shikhar