Como você arredondar para cima um número em Python?

487

Este problema está me matando. Como um arredondamento para um número UP em Python?

Eu tentei arredondar (número), mas arredondar o número para baixo. Exemplo:

round(2.3) = 2.0 and not 3, what I would like

O que eu tentei int (número + 0,5), mas arredondar o número novamente! Exemplo:

int(2.3 + .5) = 2

Então tentei a rodada (número + 0,5), mas não funcionaria em casos extremos. Exemplo:

WAIT! THIS WORKED!

Por favor informar.

bodacydo
fonte
4
round(number + .5)não funciona se o número for inteiro. round(3+.5) == 4, quando você realmente quiser 3.
Nearoo 27/01/19

Respostas:

846

O ceil função (teto):

import math
print(math.ceil(4.2))
Steve Tjoa
fonte
21
Elaboração: math.ceil retorna o menor número inteiro maior ou igual ao valor de entrada. Essa função trata a entrada como um flutuador (Python não possui variáveis ​​de tipo forte) e a função retorna um flutuador. Se você quiser um int, você pode construir um int do valor de retorno, ou seja,int(math.ceil(363))
RW trançada
9
@Sinnet: Na verdade pode-se dizer que o Python é fortemente tipado stackoverflow.com/a/11328980/5069869
Bernhard
1
@TheEspinosa: Sim, o python é definitivamente fortemente tipado, apenas algumas funções fazem perguntas sobre o tipo de alguns parâmetros e executam códigos diferentes, dependendo da resposta.
precisa
12
@RWSinnet No Python 3, math.ceilretorna um objeto inteiro real, não apenas um objeto flutuante com valor inteiro.
Arthur Tacca
Cuide de precisão float, devido a 10000000 * 0.00136 = 13600.000000000002ceil pode aumentar muitomath.ceil(10000000 * 0.00136) = 13601.0
ofthestreet
171

Sei que essa resposta é para uma pergunta há algum tempo, mas se você não deseja importar matemática e deseja arredondar, isso funciona para mim.

>>> int(21 / 5)
4
>>> int(21 / 5) + (21 % 5 > 0)
5

A primeira parte se torna 4 e a segunda parte é avaliada como "True" se houver um restante, que além disso True = 1; False = 0. Portanto, se não houver resto, ele permanecerá o mesmo número inteiro, mas se houver um restante, ele adicionará 1.

user3074620
fonte
38
Agradável. Você também pode usar //para divisão inteira, então isso se torna 21 // 5 + (21 % 5 > 0).
naught101
6
Esta é a melhor solução se apenas números inteiros estiverem envolvidos. Não floaté necessário s. Agradável.
Nico Schlömer
158

Problema interessante sobre o Python 2.x a ser lembrado:

>>> import math
>>> math.ceil(4500/1000)
4.0
>>> math.ceil(4500/1000.0)
5.0

O problema é que dividir duas entradas em python produz outra int e isso é truncado antes da chamada do teto. Você precisa transformar um valor em um valor flutuante (ou convertido) para obter um resultado correto.

Em javascript, exatamente o mesmo código produz um resultado diferente:

console.log(Math.ceil(4500/1000));
5
TrophyGeek
fonte
44
Em Python 2.x : int / int -> int e int / float -> flutuar em Python 3.x : int / int pode resultar em uma bóia
Gecco
7
você pode obter o 3.x do Python sobre o comportamento em determinadas versões do Python 2.x, permitindo que "a verdadeira divisão", como mostrado aqui
Rob Dennis
110

Se estiver trabalhando com números inteiros, uma maneira de arredondar para cima é aproveitar o fato de //arredondamentos: basta fazer a divisão no número negativo e negar a resposta. Nenhuma importação, ponto flutuante ou condicional necessário.

rounded_up = -(-numerator // denominator)

Por exemplo:

>>> print(-(-101 // 5))
21
David Bau
fonte
1
E quando você não precisa executar nenhuma operação matemática? Ou seja, você só tem um número.
Klik
2
@ Klik: então você pode dividir por 1 ==> - (-num // 1) e você está recebendo sua resposta :-) Tenha um bom dia! David Bau: proposta muito legal!
Marco SMDM
10
Cronometrei todas as respostas aqui e isso foi cinco vezes mais rápido que o próximo melhor (math.ceil). @Andreas teve o mesmo tempo
mini totent
@minitotent Isso não é surpreendente, uma vez que é simples divisão inteira e algumas operações de ciclo único. Este é o tipo de resposta que lhe dá um emprego: entendendo não apenas a linguagem, mas todas as camadas de abstrações abaixo dela.
Nearoo 6/01/19
Agradável! Eu sempre usei (num + den - 1) // den, o que é bom para intentradas com denominadores positivos, mas falha se mesmo uma única não integral floatestiver envolvida (numerador ou denominador); isso é mais mágico, mas funciona para ints e floats. Para numeradores pequenos, também é mais rápido (no CPython 3.7.2), embora, estranhamente, quando apenas o numerador é grande o suficiente para que a matemática baseada em array seja necessária, sua abordagem é mais lenta; Não está claro por que isso ocorre, uma vez que o trabalho de divisão deve ser semelhante e duas negações unárias devem ser mais baratas que adição + subtração.
ShadowRanger
56

Você também pode gostar de numpy:

>>> import numpy as np
>>> np.ceil(2.3)
3.0

Não estou dizendo que é melhor que matemática, mas se você já estava usando o numpy para outros fins, pode manter seu código consistente.

Enfim, apenas um detalhe que me deparei. Eu uso muito o numpy e fiquei surpreso por não ter sido mencionado, mas é claro que a resposta aceita funciona perfeitamente bem.

Lisa
fonte
3
Usar numpy também é bom. O mais fácil seria com a matemática, uma vez que já faz parte do python construído em bibliotecas. Faz mais sentido. Em vez disso, como você mencionou, se você usa muito numpy para outros problemas, faz sentido e é consistente usar numpy.ceil :-) Boa dica!
Marco SMDM
30

Usemath.ceil para arredondar para cima:

>>> import math
>>> math.ceil(5.4)
6.0

NOTA : A entrada deve ser flutuante.

Se você precisar de um número inteiro, ligue intpara convertê-lo:

>>> int(math.ceil(5.4))
6

Entre, use math.floorpara arredondar para baixo e roundpara o número inteiro mais próximo.

>>> math.floor(4.4), math.floor(4.5), math.floor(5.4), math.floor(5.5)
(4.0, 4.0, 5.0, 5.0)
>>> round(4.4), round(4.5), round(5.4), round(5.5)
(4.0, 5.0, 5.0, 6.0)
>>> math.ceil(4.4), math.ceil(4.5), math.ceil(5.4), math.ceil(5.5)
(5.0, 5.0, 6.0, 6.0)
kennytm
fonte
1
A entrada não precisa necessariamente ser um float se estiver usando python 3: ceil() vai cuidar disso internamente
guival
11

Estou surpreso que ninguém sugeriu

(numerator + denominator - 1) // denominator

para divisão inteira com arredondamento para cima. Costumava ser o caminho comum para C / C ++ / CUDA (cf. divup)

Andreas Schuh
fonte
2
Relevante apenas para idiomas de tipo estaticamente. Se o denominador é uma bóia, você está morto.
Bharel 06/07
Isso também funciona consistentemente se o denominador for positivo; se o denominador for negativo, você precisará adicioná-lo em 1vez de subtraí-lo ou virar os sinais do numerador e do denominador antes de realizar a matemática.
ShadowRanger
7

O valor arredondado Shure deve ser flutuante

a = 8 
b = 21
print math.ceil(a / b)
>>> 0

mas

print math.ceil(float(a) / b)
>>> 1.0
Alexey
fonte
6

Tente o seguinte:

a = 211.0
print(int(a) + ((int(a) - a) != 0))
user3712978
fonte
1
Inteligente. A ((int(a) - a) != 0)expressão retorna 1sempre que aprecisar ser arredondada. Você pode expandir sua resposta e explicar como isso funciona.
Tom Aranda
@TomAranda Alguém pode explicar como uma expressão booleana avalia um valor, por favor?
Bowen Liu
6
>>> def roundup(number):
...     return round(number+.5)
>>> roundup(2.3)
3
>>> roundup(19.00000000001)
20

Esta função não requer módulos.

PonasM
fonte
E se o seu número é 3, então seria arredondar para 4o que pode ou não ser o que alguém quer
buydadip
15
Isso funciona apenas em 99% de todos os casos. Você não pensou nisso corretamente. Tais soluções devem ser evitadas a todo custo.
Nearoo 6/01/19
então, em vez de + 5, + 0,49999999 é bom o suficiente para mim.
FlyingZebra1 28/03
5

As respostas acima estão corretas, no entanto, importar o mathmódulo apenas para essa função geralmente parece um pouco exagero para mim. Felizmente, há outra maneira de fazer isso:

g = 7/5
g = int(g) + (not g.is_integer())

Truee Falsesão interpretados como 1e 0em uma declaração envolvendo números em python. g.is_interger()traduz basicamente para g.has_no_decimal()ou g == int(g). Assim, a última declaração em Inglês lê round g down and add one if g has decimal.

Nearoo
fonte
1
E se você sentir a fantasia, você pode usar int(g) + (g % 1 > 0)em vez ;-)
Nearoo
from math import ceilparece resolver a importação de todo o módulo de matemática :)
SH7890
@ SH7890 Receio que essa linha não seja muito diferente import mathem termos do que acontece nos bastidores. Apenas elimina todos os símbolos, exceto ceil.
Nearoo 27/01/19
5

Sem importar matemática // usando o ambiente básico:

a) método / método de classe

def ceil(fl): 
  return int(fl) + (1 if fl-int(fl) else 0)

def ceil(self, fl): 
  return int(fl) + (1 if fl-int(fl) else 0)

b) lambda:

ceil = lambda fl:int(fl)+(1 if fl-int(fl) else 0)
Kuřátko Zvyk
fonte
5

Para quem deseja arredondar a / be obter um número inteiro:

Outra variante que usa divisão inteira é

def int_ceil(a, b):
    return (a - 1) // b + 1

>>> int_ceil(19, 5)
4
>>> int_ceil(20, 5)
4
>>> int_ceil(21, 5)
5
Pavel
fonte
3

Caso alguém esteja procurando arredondar para uma casa decimal específica:

import math
def round_up(n, decimals=0):
    multiplier = 10 ** decimals
    return math.ceil(n * multiplier) / multiplier
osuwireless
fonte
1

Estou surpreso por não ter visto essa resposta ainda round(x + 0.4999), então vou anotá-la. Observe que isso funciona com qualquer versão do Python. As alterações feitas no esquema de arredondamento do Python tornaram as coisas difíceis. Veja este post .

Sem importar, eu uso:

def roundUp(num):
    return round(num + 0.49)

testCases = list(x*0.1 for x in range(0, 50))

print(testCases)
for test in testCases:
    print("{:5.2f}  -> {:5.2f}".format(test, roundUp(test)))

Por que isso funciona

Dos documentos

Para os tipos internos que suportam round (), os valores são arredondados para o múltiplo mais próximo de 10 para a potência menos n; se dois múltiplos estão igualmente próximos, o arredondamento é feito para a escolha uniforme

Portanto, 2,5 é arredondado para 2 e 3,5 é arredondado para 4. Se esse não fosse o caso, o arredondamento poderia ser feito adicionando 0,5, mas queremos evitar chegar ao ponto intermediário. Portanto, se você adicionar 0,4999, você se aproximará, mas com margem suficiente para ser arredondado para o que você normalmente esperaria. Obviamente, isso falhará se o x + 0.4999for igual a [n].5000, mas isso é improvável.

Klik
fonte
2
Usando 0.4999, ele falhará em fornecer um resultado correto para qualquer entrada entre ???. 0000 e ???. 0001 (intervalo aberto), não apenas exatamente .0001. Por exemplo, se você tentar com 3.00005, obterá um resultado de 3 em vez do esperado 4. É claro que você pode diminuir a probabilidade de isso acontecer adicionando mais e mais dígitos até a precisão máxima dos flutuadores, mas qual é o apontar para isso, se houver soluções mais robustas e intuitivas, como usar math.ceil()?
blubberdiblub
@blubberdiblub Na minha resposta, afirmo Without importing I use:. Eu também mencionei que falhará se o x + 0.4999for igual a [n].5000.
Klik
4
Sim, você declara em sua resposta que sua solução está sem importação, mas não vejo o valor dela. O mathmódulo math.ceil()está na biblioteca padrão, disponível em todos os lugares para todos os fins práticos, sem a instalação de itens extras. E com relação à sua menção de quando falha, isso está incompleto em sua resposta, pois falha por um intervalo inteiro, não apenas por um único ponto. Tecnicamente, você pode argumentar que está correto, como diz se, e não se , mas isso causará a impressão no leitor casual de que é menos provável do que realmente é.
blubberdiblub
0

Para fazer isso sem qualquer importação:

>>> round_up = lambda num: int(num + 1) if int(num) != num else int(num)
>>> round_up(2.0)
2
>>> round_up(2.1)
3
gorttar
fonte
0

Eu sei que isso já faz um bom tempo, mas achei uma resposta bastante interessante, então aqui vai:

-round(-x-0.5)

Isso corrige os casos de arestas e funciona para números positivos e negativos e não requer nenhuma importação de função

Felicidades

Fenmaz
fonte
2
Isso ainda -round(-x-0.3) = x
termina
0

quando você opera 4500/1000 em python, o resultado será 4, porque, para o python padrão, asume como número inteiro, logicamente: 4500/1000 = 4.5 -> int (4.5) = 4 e o teto de 4 obviamente é 4

usando 4500 / 1000.0, o resultado será 4,5 e o teto de 4,5 -> 5

Usando javascript, você receberá 4,5 como resultado de 4500/1000, porque o javascript assume apenas o resultado como "tipo numérico" e retorna um resultado diretamente como float

Boa sorte!!

erick vicente
fonte
Isso é verdade apenas no Python 2.x. No Python 3, a divisão com um único /sempre resulta em uma flutuação, assim 4500/1000como sempre é 4.5.
Nearoo 19/06
0

Se você não deseja importar nada, sempre pode escrever sua própria função simples como:

def RoundUP(num): if num== int(num): return num return int(num + 1)

Sebin
fonte
2
Isso não funciona se num for 2.05. Você precisa ter pelo menos tantos dígitos com 9 quanto sua entrada, deixando-o com 0,999 ... que é 1. Mas a caixa de canto 2 é arredondada novamente. - Bem, acho que há uma razão pela qual math.ceil está lá.
Johannes Maria Frank
-1

Você pode usar a disposição do piso e adicionar 1 a ela. 2,3 // 2 + 1

user6612280
fonte
2
ou usar ceil(), em vez de estranhamente fazendo o oposto e, em seguida, compensando
guival
2
Isso não vai funcionar. Por exemplo:from math import ceil; assert 4 // 2 + 1 == ceil(4 / 2)
Carl Thomé
-1

Eu acho que você está confundindo os mecanismos de trabalho entre int()e round().

int()sempre trunca os números decimais se um número flutuante for fornecido; enquanto que round(), no caso de 2.5onde 2e 3ambos estão a uma distância igual 2.5, o Python retorna o que estiver mais distante do ponto 0.

round(2.5) = 3
int(2.5) = 2
SooBin Kim
fonte
"arredondar para cima" significa que, por exemplo, 2.3é transformado 3, o que acontece em nenhum dos seus exemplos.
Nearoo 19/06
-2

Minha parte

Eu testei print(-(-101 // 5)) = 21dado o exemplo acima.

Agora, para arredondar para cima:

101 * 19% = 19.19

Eu não posso usar, **então eu espalhei a multiplicação para divisão:

(-(-101 //(1/0.19))) = 20
andres
fonte
-3

Eu sou basicamente iniciante no Python, mas se você está apenas tentando arredondar em vez de diminuir, por que não:

round(integer) + 1
Daniel
fonte
2
Isso não vai funcionar para qualquer inteiro i, onde 2,5 <inteiro <3. O valor desejado após o arredondamento para cima é 3, mas a sua expressão irá transformá-lo em 4.
Pranav Shukla
1
Eu acho que você quer dizer round(integer + 0.5)Isto é o que costumo fazer
Klik