Arredonde para 5 (ou outro número) em Python


162

Existe uma função interna que pode ser arredondada da seguinte maneira?

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

Respostas:


304

Não conheço uma função padrão no Python, mas isso funciona para mim:

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)

É fácil ver por que o que foi dito acima funciona. Você deseja garantir que seu número dividido por 5 seja um número inteiro, arredondado corretamente. Então, primeiro fazemos exatamente isso ( round(float(x)/5)onde floaté necessário apenas no Python2) e, depois que dividimos por 5, multiplicamos por 5 também. A conversão final para inté porque round()retorna um valor de ponto flutuante no Python 2.

Tornei a função mais genérica, fornecendo um baseparâmetro, assumindo o padrão 5.


3
Se apenas números inteiros e arredondar para baixo, você também pode fazer apenasx // base * base
#

7
este sou eu sendo paranóico, mas eu prefiro usar floor()e ceil()não base * floor(x/base)
transmitir

1
@ user666412 math.floore math.ceilnão permita o uso com uma base personalizada, portanto, a preferência é irrelevante.
Acumenus 23/09/19

48

Para arredondar para valores não inteiros, como 0,05:

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

Achei isso útil, pois eu poderia apenas fazer uma pesquisa e substituir no meu código para alterar "round (" para "myround (", sem precisar alterar os valores dos parâmetros).


2
Você pode usar: o def my_round(x, prec=2, base=0.05): return (base * (np.array(x) / base).round()).round(prec) qual aceita matrizes numpy também.
Saubhik

23

É apenas uma questão de escala

>>> 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

Remover o 'resto' funcionaria:

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

Se o valor já for um número inteiro:

rounded = val - val % 5

Como uma função:

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

Eu gosto desta resposta para arredondar para o valor fracionário mais próximo. ou seja, se eu quiser apenas incrementos de 0,25.
jersey bean


9

round (x [, n]): os valores são arredondados para o múltiplo mais próximo de 10 para a potência menos n. Então, se n é negativo ...

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

Como 10 = 5 * 2, você pode usar a divisão inteira e a multiplicação com 2, em vez da divisão e multiplicação flutuante com 5.0. Não que isso importe muito, a menos que você goste de mudar um pouco

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

1
+1 por nos mostrar que round () pode lidar com arredondamentos para múltiplos diferentes de 1,0, incluindo valores mais altos. (Note, no entanto, que a abordagem de mudança de bit não irá funcionar com flutuadores, para não mencionar que é muito menos legível para a maioria dos programadores.)
Peter Hansen

1
@ Peter Hansen, obrigado pelo +1. Precisa ter um int (x) para que a mudança de bits funcione com flutuadores. Concordei que não era o mais legível e eu não usaria isso sozinho, mas gostei da "pureza" dele envolvendo apenas 1 e não 2 ou 5.
Pwdyson

6

Desculpe, eu queria comentar a resposta de Alok Singhai, mas isso não me deixa devido à falta de reputação = /

De qualquer forma, podemos generalizar mais um passo e prosseguir:

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

Isso nos permite usar bases não inteiras, como .25qualquer outra base fracionária.


Por favor, não tente ignorar as novas restrições de usuário postando um comentário como resposta. Existem restrições por um motivo . Leve isso em consideração como um possível motivo para Por que e como algumas respostas são excluídas?
Adeus StackExchange

4

Versão modificada do divround :-)

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

Então, neste caso, você usa divround (valor, 5, 3)? ou talvez dividir (valor, 5, 2,5)?
Pwdyson

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

4

Usar:

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

Ele não usa multiplicação e não converterá de / para carros alegóricos.

Arredondando para o múltiplo mais próximo de 10:

>>> 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 você pode ver, ele funciona para números negativos e positivos. Os laços (por exemplo, -15 e 15) sempre serão arredondados para cima.

Um exemplo semelhante que arredonda para o múltiplo mais próximo de 5, demonstrando que ele também se comporta conforme o esperado para uma "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

Caso alguém precise de "arredondamentos financeiros" (0,5 arredondamentos sempre acima):

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'))))

Conforme a documentação, outras opções de arredondamento são:

ROUND_CEILING (em direção ao infinito),
ROUND_DOWN (em direção a zero),
ROUND_FLOOR (em direção a -Infinity),
ROUND_HALF_DOWN (para o mais próximo com laços indo em direção a zero),
ROUND_HALF_EVEN (para o mais próximo com laços indo para o número inteiro mais próximo),
ROUND_HALF_UP (para o mais próximo com gravatas indo longe de zero) ou
ROUND_UP (longe de zero).
ROUND_05UP (longe de zero, se o último dígito depois de arredondar para zero fosse 0 ou 5; caso contrário, para zero)

Por padrão, o Python usa ROUND_HALF_EVEN, pois possui algumas vantagens estatísticas (os resultados arredondados não são tendenciosos).


2

Para números inteiros e com Python 3:

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


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

Produção:

>>> [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

Próximo múltiplo de 5

Considere que 51 precisa ser convertido para 55:

code here

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

1

Aqui está o meu código C. Se eu entendi direito, deveria ser algo assim;

#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);
  }
}

e isso também arredonda para o múltiplo mais próximo de 5, em vez de apenas arredondar para cima;

#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

Outra maneira de fazer isso (sem operadores explícitos de multiplicação ou divisão):

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

-3

Você pode "enganar" o int()arredondamento em vez de arredondar para baixo, adicionando 0.5ao número para o qual você passa int().


2
Na verdade, isso não responde à pergunta
Uri Agassi
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.