Eu descobri sobre o //
operador em Python que em Python 3 faz divisão com chão.
Existe um operador que divide com teto em vez disso? (Eu sei sobre o /
operador que no Python 3 faz a divisão de ponto flutuante.)
Eu descobri sobre o //
operador em Python que em Python 3 faz divisão com chão.
Existe um operador que divide com teto em vez disso? (Eu sei sobre o /
operador que no Python 3 faz a divisão de ponto flutuante.)
Respostas:
Não há operador que divida com teto. Você precisa import math
e usarmath.ceil
Você pode simplesmente fazer a divisão do piso de cabeça para baixo:
def ceildiv(a, b):
return -(-a // b)
Isso funciona porque o operador de divisão do Python faz a divisão de piso (ao contrário de C, onde a divisão inteira trunca a parte fracionária).
Isso também funciona com os grandes inteiros do Python, porque não há conversão de ponto flutuante (com perdas).
Aqui está uma demonstração:
>>> from __future__ import division # a/b is float division
>>> from math import ceil
>>> b = 3
>>> for a in range(-7, 8):
... print(["%d/%d" % (a, b), int(ceil(a / b)), -(-a // b)])
...
['-7/3', -2, -2]
['-6/3', -2, -2]
['-5/3', -1, -1]
['-4/3', -1, -1]
['-3/3', -1, -1]
['-2/3', 0, 0]
['-1/3', 0, 0]
['0/3', 0, 0]
['1/3', 1, 1]
['2/3', 1, 1]
['3/3', 1, 1]
['4/3', 2, 2]
['5/3', 2, 2]
['6/3', 2, 2]
['7/3', 3, 3]
int
não tem (bem, nenhuma significativa; no Python de 64 bits você está limitado a 30 * (2**63 - 1)
números de bits), e mesmo a conversão temporária para float
pode perder informações. Compare math.ceil((1 << 128) / 10)
com -(-(1 << 128) // 10)
.
Você poderia fazer (x + (d-1)) // d
ao dividir x
por d
, ou seja (x + 4) // 5
.
math.ceil()
.
sys.float_info.max
e não requer importação.
def ceiling_division(n, d):
return -(n // -d)
Uma reminiscência do truque de levitação de Penn & Teller , isso "vira o mundo de cabeça para baixo (com negação), usa divisão de piso simples (onde o teto e o piso foram trocados) e, em seguida, vira o mundo do lado direito (com negação novamente) "
def ceiling_division(n, d):
q, r = divmod(n, d)
return q + bool(r)
A função divmod () fornece (a // b, a % b)
para inteiros (isso pode ser menos confiável com flutuações devido ao erro de arredondamento). O passo com bool(r)
adiciona um ao quociente sempre que houver um resto diferente de zero.
def ceiling_division(n, d):
return (n + d - 1) // d
Transforme o numerador para cima para que a divisão do piso seja arredondada para baixo até o teto pretendido. Observe que isso só funciona para inteiros.
def ceiling_division(n, d):
return math.ceil(n / d)
O código math.ceil () é fácil de entender, mas converte de ints para floats e vice-versa. Isso não é muito rápido e pode ter problemas de arredondamento. Além disso, ele se baseia na semântica do Python 3, em que a "verdadeira divisão" produz um float e a função ceil () retorna um inteiro.
-(-a // b)
o_O
-(a // -b)
é mais rápido do que -(-a // b)
, pelo menos ao cronometrar exemplos de brinquedos compython -m timeit ...
Você sempre pode fazer isso inline também
((foo - 1) // bar) + 1
Em python3, isso é apenas uma ordem de magnitude mais rápido do que forçar a divisão flutuante e chamar ceil (), desde que você se preocupe com a velocidade. O que você não deveria fazer, a menos que tenha provado através do uso que você precisa.
>>> timeit.timeit("((5 - 1) // 4) + 1", number = 100000000)
1.7249219375662506
>>> timeit.timeit("ceil(5/4)", setup="from math import ceil", number = 100000000)
12.096064013894647
number=100000000
). Por chamada, a diferença é bem insignificante.
foo = -8
e bar = -4
, por exemplo, a resposta deve ser 2, não 3, exatamente como -8 // -4
. A divisão do piso Python é definida como "a divisão matemática com a função 'piso' aplicada ao resultado" e a divisão do teto é a mesma coisa, mas com em ceil()
vez de floor()
.
Observe que math.ceil é limitado a 53 bits de precisão. Se você estiver trabalhando com números inteiros grandes, pode não obter resultados exatos.
A biblioteca gmpy2 fornece uma c_div
função que usa arredondamento de teto.
Isenção de responsabilidade: eu mantenho o gmpy2.
python2 -c 'from math import ceil;assert ceil(11520000000000000102.9)==11520000000000000000'
(bem como a substituição python3
) AMBOS sãoTrue
Solução simples: a // b + 1