redondear - redondeo de decimales python
Redondea al tercer lugar decimal en Python (8)
¿Cómo puedo redondear un número al tercer lugar decimal en python, por ejemplo:
0.022499999999999999
Debe redondear hasta 0.03
0.1111111111111000
Debe redondear hasta 0.12
Si hay algún valor en el tercer lugar decimal, quiero que siempre se redondee dejándome 2 valores detrás del punto decimal.
Esto depende del comportamiento que desee al considerar números positivos y negativos, pero si desea algo que siempre redondea a un valor mayor (por ejemplo, 2.0449 -> 2.05, -2.0449 -> -2.04), entonces puede hacer:
round(x + 0.005, 2)
o un poco más lujoso
def round_up(x, place):
return round(x + 5 * 10**(-1 * (place + 1)), place)
Esto también parece funcionar de la siguiente manera:
round(144, -1)
# 140
round_up(144, -1)
# 150
round_up(1e308, -307)
# 1.1e308
Extrapolando de la respuesta de Edwin:
from math import ceil, floor
def float_round(num, places = 0, direction = floor):
return direction(num * (10**places)) / float(10**places)
Usar:
>>> 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
La función redonda declarada no funciona para enteros definidos como:
a = 8
redondo (a, 3)
8.0
a = 8.00
redondo (a, 3)
8.0
a = 8.000000000000000000000000
redondo (a, 3)
8.0
pero, trabaja para:
r = 400 / 3.0
r
133.33333333333334
redondo (r, 3)
133.333
Además, los decimales como 2.675 se redondean como 2.67, no 2.68.
Mejor usar el otro método proporcionado anteriormente.
Tenga en cuenta que el truco ceil(num * 100) / 100
se bloqueará en algunas entradas degeneradas, como 1e308. Es posible que esto no ocurra a menudo, pero puedo decir que solo me costó un par de días. Para evitar esto, "sería bueno si" ceil()
y floor()
tomaron un argumento de lugares decimales, como round()
hace ... Mientras tanto, ¿alguien sabe una alternativa limpia que no se bloquee en entradas como esta? Tuve algunas esperanzas para el paquete decimal
, pero parece morir también:
>>> 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''>]
Por supuesto, se podría decir que el bloqueo es el único comportamiento sensato en tales entradas, pero diría que no es el redondeo sino la multiplicación lo que está causando el problema (por eso, por ejemplo, 1e306 no falla), y una implementación más limpia de La redondeo del n-lugar evitaría el truco de multiplicación.
Python incluye la función round()
que le permite especificar el número de dígitos que desea. De la documentación:
round(x[, n])
Devuelva el valor de punto flotante x redondeado a n dígitos después del punto decimal. Si se omite n, el valor predeterminado es cero. El resultado es un número de punto flotante. Los valores se redondean al múltiplo más cercano de 10 a la potencia menos n; si dos múltiplos están igualmente cerca, el redondeo se realiza fuera de 0 (así, por ejemplo, la ronda (0.5) es 1.0 y la ronda (-0.5) es -1.0).
Por lo tanto, querría usar round(x, 2)
para hacer el redondeo normal. Para asegurarse de que el número siempre esté redondeado, deberá utilizar la función ceil(x)
. Del mismo modo, para redondear hacia abajo use floor(x)
.
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:
# woops, 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
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
from math import ceil
num = 0.1111111111000
num = ceil(num * 100) / 100.0
Ver:
documentación de math.ceil
documentación round
- probablemente querrá revisar esto de todos modos para futuras referencias
x = math.ceil(x * 100.0) / 100.0