multiplicacion - redondear un numero en python 3
Python redondea un entero hasta el próximo cien (8)
Advertencia: optimizaciones prematuras por delante ...
Dado que muchas de las respuestas aquí hacen el tiempo de esto, quería agregar otra alternativa.
Tomando @Martin Geisler ''s
def roundup(x):
return x if x % 100 == 0 else x + 100 - x % 100
(que me gusta mejor por varias razones)
pero teniendo en cuenta el% de acción
def roundup2(x):
x100= x % 100
return x if x100 == 0 else x + 100 - x100
Otorga una mejora de velocidad ~ 20% sobre el original
def roundup3(x):
x100 = x % 100
return x if not x100 else x + 100 - x100
Es aún mejor y es ~ 36% más rápido que el original
finalmente pensé que podía dejar caer al operador " not
y cambiar el orden de las ramas con la esperanza de que esto también aumentara la velocidad, pero me desconcerté al descubrir que en realidad es más lento y es solo un 23% más rápido que el original.
def roundup4(x):
x100 = x % 100
return x + 100 - x100 if x100 else x
>python -m timeit -s "x = 130" "x if x % 100 == 0 else x + 100 - x % 100"
1000000 loops, best of 3: 0.359 usec per loop
>python -m timeit -s "x = 130" "x100 = x % 100" "x if x100 == 0 else x + 100 - x100"
1000000 loops, best of 3: 0.287 usec per loop
>python -m timeit -s "x = 130" "x100 = x % 100" "x if not x100 else x + 100 - x100"
1000000 loops, best of 3: 0.23 usec per loop
>python -m timeit -s "x = 130" "x100 = x % 100" "x + 100 - x100 if x100 else x"
1000000 loops, best of 3: 0.277 usec per loop
las explicaciones sobre por qué 3 es más rápido que 4 serían bienvenidas.
Parece que ya debería haber pedido cientos (juegos de palabras son divertidos =) de veces, pero solo puedo encontrar la función para redondear carrozas. ¿Cómo puedo redondear un entero, por ejemplo: 130 -> 200
?
Aquí hay una forma general de redondear al múltiplo más cercano de cualquier entero positivo:
def roundUpToMultiple(number, multiple):
num = number + (multiple - 1)
return num - (num % multiple)
Uso de muestra:
>>> roundUpToMultiple(101, 100) 200 >>> roundUpToMultiple(654, 321) 963
El redondeo generalmente se realiza en números de coma flotante, y aquí hay tres funciones básicas que debe conocer: round
(redondea al entero más cercano), math.floor
. math.floor
(siempre redondea hacia abajo) y math.ceil
( math.ceil
siempre hacia arriba).
Usted pregunta por enteros y redondea cientos, pero aún podemos usar math.ceil
siempre que sus números sean menores que 2 53 . Para usar math.ceil
, solo dividimos entre 100 primero, redondeo hacia arriba y luego multiplicamos con 100:
>>> import math
>>> def roundup(x):
... return int(math.ceil(x / 100.0)) * 100
...
>>> roundup(100)
100
>>> roundup(101)
200
Al dividir por 100 primero y luego multiplicar por 100, "desplaza" dos lugares decimales a la derecha e izquierda para que math.ceil
trabaje en los cientos. Puede usar 10**n
lugar de 100 si desea redondear a decenas ( n = 1
), miles ( n = 3
), etc.
Una forma alternativa de hacerlo es evitar los números de coma flotante (tienen una precisión limitada) y en su lugar usar enteros solamente. Los enteros tienen una precisión arbitraria en Python, por lo que le permite redondear números de cualquier tamaño. La regla para el redondeo es simple: encuentre el resto después de la división con 100, y agregue 100 menos este resto si no es cero:
>>> def roundup(x):
... return x if x % 100 == 0 else x + 100 - x % 100
Esto funciona para números de cualquier tamaño:
>>> roundup(100)
100
>>> roundup(130)
200
>>> roundup(1234567891234567891)
1234567891234567900L
Hice un mini-benchmark de las dos soluciones:
$ python -m timeit -s ''import math'' -s ''x = 130'' ''int(math.ceil(x/100.0)) * 100''
1000000 loops, best of 3: 0.364 usec per loop
$ python -m timeit -s ''x = 130'' ''x if x % 100 == 0 else x + 100 - x % 100''
10000000 loops, best of 3: 0.162 usec per loop
La solución entera pura es más rápida en un factor de dos en comparación con la solución math.ceil
.
Thomas propuso una solución basada en enteros que es idéntica a la que tengo arriba, excepto que usa un truco multiplicando los valores booleanos. Es interesante ver que no hay una ventaja de velocidad al escribir el código de esta manera:
$ python -m timeit -s ''x = 130'' ''x + 100*(x%100>0) - x%100''
10000000 loops, best of 3: 0.167 usec per loop
Como observación final, permítanme también señalar que si hubieran querido redondear 101-149 a 100 y redondear 150-199 a 200, por ejemplo, redondear a la centena más cercana , entonces la función de round
incorporada puede hacer eso por ustedes :
>>> int(round(130, -2))
100
>>> int(round(170, -2))
200
Esta es una respuesta tardía, pero hay una solución simple que combina los mejores aspectos de las respuestas existentes: el siguiente múltiplo de 100
desde x
es x - x % -100
(o si lo prefiere, x + (-x) % 100
)
>>> x = 130
>>> x -= x % -100 # Round x up to next multiple of 100.
>>> x
200
Esto es rápido y simple, da los resultados correctos para cualquier número entero x
(como la respuesta de John Machin) y también da resultados razonables (módulo las advertencias habituales sobre la representación de punto flotante) si x
es un flotador (como la respuesta de Martin Geisler).
>>> x = 0.1
>>> x -= x % -100
>>> x
100.0
Para a
entero no negativo, b
positivo, ambos enteros:
>>> rup = lambda a, b: (a + b - 1) // b * b
>>> [(x, rup(x, 100)) for x in (199, 200, 201)]
[(199, 200), (200, 200), (201, 300)]
Actualización La respuesta actualmente aceptada se desmorona con números enteros tales que float (x) / float (y) no se puede representar con precisión como float
. Vea este código:
import math
def geisler(x, y): return int(math.ceil(x / float(y))) * y
def orozco(x, y): return x + y * (x % y > 0) - x % y
def machin(x, y): return (x + y - 1) // y * y
for m, n in (
(123456789123456789, 100),
(1234567891234567891, 100),
(12345678912345678912, 100),
):
print; print m, "m"; print n, "n"
for func in (geissler, orozco, machin):
print func(m, n), func.__name__
Salida:
123456789123456789 m
100 n
123456789123456800 geisler
123456789123456800 orozco
123456789123456800 machin
1234567891234567891 m
100 n
1234567891234568000 geisler <<<=== wrong
1234567891234567900 orozco
1234567891234567900 machin
12345678912345678912 m
100 n
12345678912345680000 geisler <<<=== wrong
12345678912345679000 orozco
12345678912345679000 machin
Y aquí hay algunos tiempos:
>/python27/python -m timeit -s "import math;x =130" "int(math.ceil(x/100.0))*100"
1000000 loops, best of 3: 0.342 usec per loop
>/python27/python -m timeit -s "x = 130" "x + 100 * (x % 100 > 0) - x % 100"
10000000 loops, best of 3: 0.151 usec per loop
>/python27/python -m timeit -s "x = 100" "(x + 99) // 100 * 100"
10000000 loops, best of 3: 0.0903 usec per loop
Prueba esto:
import math
def ceilm(number,multiple):
''''''Returns a float rounded up by a factor of the multiple specified''''''
return math.ceil(float(number)/multiple)*multiple
Uso de muestra:
>>> ceilm(257,5)
260
>>> ceilm(260,5)
260
Prueba esto:
int(round(130 + 49, -2))
Si su int es x: x + 100 - x % 100
Sin embargo, como se señaló en los comentarios, esto devolverá 200 si x==100
.
Si este no es el comportamiento esperado, puede usar x + 100*(x%100>0) - x%100