Я узнал об //
операторе в Python, который в Python 3 делает разделение с полом.
Есть ли вместо этого оператор деления на ceil? (Я знаю об /
операторе, который в Python 3 выполняет деление с плавающей запятой.)
Я узнал об //
операторе в Python, который в Python 3 делает разделение с полом.
Есть ли вместо этого оператор деления на ceil? (Я знаю об /
операторе, который в Python 3 выполняет деление с плавающей запятой.)
Ответы:
Нет оператора деления с ceil. Вам нужно import math
и использоватьmath.ceil
Можно просто сделать перевернутое деление этажа:
def ceildiv(a, b):
return -(-a // b)
Это работает, потому что оператор деления Python выполняет деление пола (в отличие от C, где целочисленное деление усекает дробную часть).
Это также работает с большими целыми числами Python, потому что здесь нет преобразования с плавающей запятой (с потерями).
Вот демонстрация:
>>> 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
нет (ну, никаких значимых; на 64-битном Python вы ограничены 30 * (2**63 - 1)
битовыми числами), и даже временное преобразование в float
может потерять информацию. Сравните math.ceil((1 << 128) / 10)
с -(-(1 << 128) // 10)
.
Вы могли бы сделать (x + (d-1)) // d
при делении x
на d
, то есть (x + 4) // 5
.
sys.float_info.max
, и не требует импорта.
def ceiling_division(n, d):
return -(n // -d)
Напоминающий трюк с левитацией Пенна и Теллера , это «переворачивает мир вверх дном (с отрицанием), использует простое деление пола (где потолок и пол поменяны местами), а затем переворачивает мир правой стороной вверх (снова с отрицанием) "
def ceiling_division(n, d):
q, r = divmod(n, d)
return q + bool(r)
Функция divmod () дает (a // b, a % b)
для целых чисел (это может быть менее надежным с числами с плавающей запятой из-за ошибки округления). Шаг с bool(r)
добавляет единицу к частному всякий раз, когда есть ненулевой остаток.
def ceiling_division(n, d):
return (n + d - 1) // d
Переместите числитель вверх, чтобы разделение пола округлялось до предполагаемого потолка. Обратите внимание, это работает только для целых чисел.
def ceiling_division(n, d):
return math.ceil(n / d)
Код math.ceil () прост для понимания, но он преобразует целые числа в числа с плавающей запятой и обратно. Это не очень быстро и может иметь проблемы с округлением. Кроме того, он опирается на семантику Python 3, где «истинное деление» производит число с плавающей запятой, а функция ceil () возвращает целое число.
-(-a // b)
o_O
-(a // -b)
это быстрее, чем -(-a // b)
, по крайней мере, при выборе времени игрушечных примеров сpython -m timeit ...
Вы всегда можете просто сделать это встроенным
((foo - 1) // bar) + 1
В python3 это всего лишь на порядок быстрее, чем принудительное деление с плавающей запятой и вызов ceil (), при условии, что вы заботитесь о скорости. Чего вам не следует делать, если вы не доказали на практике, что вам это нужно.
>>> 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
). За один звонок разница незначительная.
foo = -8
и bar = -4
, например, ответ должен быть 2, а не 3, как -8 // -4
. Разделение полов в Python определяется как «математическое деление с применением функции« пол »к результату», а деление потолка - это то же самое, но ceil()
вместо floor()
.
Обратите внимание, что math.ceil ограничен 53 битами точности. Если вы работаете с большими целыми числами, вы можете не получить точных результатов.
Библиотека gmpy2 предоставляет c_div
функцию, которая использует округление потолка.
Отказ от ответственности: я поддерживаю gmpy2.
python2 -c 'from math import ceil;assert ceil(11520000000000000102.9)==11520000000000000000'
(а также заменяющие python3
) ОБЕИTrue
Простое решение: a // b + 1