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
Pydev UA
fonte

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.

Alok Singhal
fonte
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).

CCKx
fonte
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
amo-ej1
fonte
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)
hgdeoro
fonte
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
14
def round_to_next5(n):
    return n + (5 - n) % 5
Andy Wong
fonte
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
pwdyson
fonte
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.

ArturJ
fonte
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
Christian Hausknecht
fonte
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
wouter bolsterlee
fonte
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).

Piotr Siejda
fonte
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]
Sylvain Leroux
fonte
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;
vijay
fonte
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);
  }
}
Ege Merey
fonte
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))
cosmic_inquiry
fonte
-3

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

Franciska Zsiros
fonte
2
Na verdade, isso não responde à pergunta
Uri Agassi