Redondea a 5 (u otro número) en Python


162

¿Existe una función incorporada que pueda redondear como la siguiente?

10 -> 10
12 -> 10
13 -> 15
14 -> 15
16 -> 15
18 -> 20

Respuestas:


304

No sé de una función estándar en Python, pero esto funciona para mí:

Python 2

def myround(x, base=5):
    return int(base * round(float(x)/base))

Python3

def myround(x, base=5):
    return base * round(x/base)

Es fácil ver por qué funciona lo anterior. Desea asegurarse de que su número dividido entre 5 sea un número entero, correctamente redondeado. Entonces, primero hacemos exactamente eso ( round(float(x)/5)donde floatsolo se necesita en Python2), y luego, dado que dividimos entre 5, también multiplicamos por 5. La conversión final a intes porque round()devuelve un valor de punto flotante en Python 2.

Hice la función más genérica dándole un baseparámetro, por defecto a 5.


3
Si solo son enteros y redondean hacia abajo, entonces también puedes hacerlox // base * base
Tjorriemorrie

77
soy yo paranoico, pero prefiero usarlo floor()y ceil()no usarlo :base * floor(x/base)
user666412

1
@ user666412 math.floory math.ceilno permite su uso con una base personalizada, por lo que la preferencia es irrelevante.
Acumenus

48

Para redondear a valores no enteros, como 0.05:

def myround(x, prec=2, base=.05):
  return round(base * round(float(x)/base),prec)

Encontré esto útil ya que podía hacer una búsqueda y reemplazar en mi código para cambiar "round (" a "myround (", sin tener que cambiar los valores de los parámetros.


2
Puede usar: def my_round(x, prec=2, base=0.05): return (base * (np.array(x) / base).round()).round(prec) que acepta matrices numpy también.
saubhik

23

Es solo cuestión de escalar

>>> a=[10,11,12,13,14,15,16,17,18,19,20]
>>> for b in a:
...     int(round(b/5.0)*5.0)
... 
10
10
10
15
15
15
15
15
20
20
20

14

Eliminar el 'descanso' funcionaría:

rounded = int(val) - int(val) % 5

Si el valor es ya un entero:

rounded = val - val % 5

Como una función:

def roundint(value, base=5):
    return int(value) - int(value) % int(base)

Me gusta esta respuesta para redondear al valor fraccionario más cercano. es decir, si solo quiero incrementos de 0.25.
jersey bean


9

round (x [, n]): los valores se redondean al múltiplo más cercano de 10 a la potencia menos n. Entonces, si n es negativo ...

def round5(x):
    return int(round(x*2, -1)) / 2

Como 10 = 5 * 2, puede usar la división entera y la multiplicación con 2, en lugar de la división flotante y la multiplicación con 5.0. No es que eso importe mucho, a menos que te guste un poco de desplazamiento

def round5(x):
    return int(round(x << 1, -1)) >> 1

1
+1 por mostrarnos que round () puede manejar el redondeo a múltiplos distintos de 1.0, incluidos los valores más altos. (Tenga en cuenta, sin embargo, que el enfoque de cambio de bits no funcionará con flotadores, sin mencionar que es mucho menos legible para la mayoría de los programadores)
Peter Hansen

1
@ Peter Hansen gracias por el +1. Necesita tener un int (x) para que el desplazamiento de bits funcione con flotantes. No estaba de acuerdo con lo más legible y no lo usaría yo mismo, pero me gustó la "pureza" que solo involucra 1 y no 2 o 5.
pwdyson

6

Lo siento, quería comentar la respuesta de Alok Singhai, pero no me lo permite debido a la falta de reputación = /

De todos modos, podemos generalizar un paso más e ir:

def myround(x, base=5):
    return base * round(float(x) / base)

Esto nos permite usar bases no enteras, como .25o cualquier otra base fraccional.


No intente eludir las restricciones de nuevos usuarios publicando un comentario como respuesta. Las restricciones existen por una razón . Tenga esto en cuenta como una posible razón de por qué y cómo se eliminan algunas respuestas.
Adiós StackExchange el

4

Versión modificada de divround :-)

def divround(value, step, barrage):
    result, rest = divmod(value, step)
    return result*step if rest < barrage else (result+1)*step

entonces en este caso usas divround (valor, 5, 3)? o tal vez divround (valor, 5, 2.5)?
pwdyson

divround (valor, 5, 3), exactamente.
Christian Hausknecht

4

Utilizar:

>>> def round_to_nearest(n, m):
        r = n % m
        return n + m - r if r + r >= m else n - r

No usa multiplicación y no convertirá de / a flotantes.

Redondeando al múltiplo de 10 más cercano:

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 10)))
-21  =>  -20
-18  =>  -20
-15  =>  -10
-12  =>  -10
 -9  =>  -10
 -6  =>  -10
 -3  =>    0
  0  =>    0
  3  =>    0
  6  =>   10
  9  =>   10
 12  =>   10
 15  =>   20
 18  =>   20
 21  =>   20
 24  =>   20
 27  =>   30

Como puede ver, funciona tanto para números negativos como positivos. Los empates (por ejemplo, -15 y 15) siempre se redondearán hacia arriba.

Un ejemplo similar que se redondea al múltiplo más cercano de 5, lo que demuestra que también se comporta como se espera para una "base" diferente:

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 5)))
-21  =>  -20
-18  =>  -20
-15  =>  -15
-12  =>  -10
 -9  =>  -10
 -6  =>   -5
 -3  =>   -5
  0  =>    0
  3  =>    5
  6  =>    5
  9  =>   10
 12  =>   10
 15  =>   15
 18  =>   20
 21  =>   20
 24  =>   25
 27  =>   25

2

En caso de que alguien necesite "redondeo financiero" (0.5 rondas siempre arriba):

def myround(x, base=5):
    roundcontext = decimal.Context(rounding=decimal.ROUND_HALF_UP)
    decimal.setcontext(roundcontext)
    return int(base *float(decimal.Decimal(x/base).quantize(decimal.Decimal('0'))))

Según la documentación, otras opciones de redondeo son:

ROUND_CEILING (hacia Infinity),
ROUND_DOWN (hacia cero),
ROUND_FLOOR (hacia -Infinity),
ROUND_HALF_DOWN (al más cercano con lazos que van hacia cero),
ROUND_HALF_EVEN (al más cercano con lazos que van al número entero más cercano),
ROUND_HALF_UP (al más cercano con lazos que van lejos de cero) o
ROUND_UP (lejos de cero).
ROUND_05UP (lejos de cero si el último dígito después del redondeo hacia cero hubiera sido 0 o 5; de lo contrario hacia cero)

Por defecto, Python usa ROUND_HALF_EVEN ya que tiene algunas ventajas estadísticas (los resultados redondeados no están sesgados).


2

Para enteros y con Python 3:

def divround_down(value, step):
    return value//step*step


def divround_up(value, step):
    return (value+step-1)//step*step

Productor:

>>> [divround_down(x,5) for x in range(20)]
[0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15]
>>> [divround_up(x,5) for x in range(20)]
[0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20, 20, 20]


1

Siguiente múltiplo de 5

Considere que 51 necesita convertirse a 55:

code here

mark = 51;
r = 100 - mark;
a = r%5;
new_mark = mark + a;

1

Aquí está mi código C. Si lo entiendo correctamente, debería ser algo como esto;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        number++;
  printf("%d\n",number);
  }
}

y esto también se redondea al múltiplo más cercano de 5 en lugar de simplemente redondear hacia arriba;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        if (number%5 < 3)
            number--;
        else
        number++;
  printf("nearest multiple of 5 is: %d\n",number);
  }
}

1

Otra forma de hacer esto (sin operadores explícitos de multiplicación o división):

def rnd(x, b=5):
    return round(x + min(-(x % b), b - (x % b), key=abs))

-3

Puede "engañar" int()para redondear en lugar de redondear hacia abajo agregando 0.5al número al que pasa int().


2
Esto en realidad no responde a la pregunta
Uri Agassi
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.