Существует ли потолочный эквивалент оператора//в Python?

Я узнал об операторе // в Python, который в Python 3 делает разделение с полом.

Есть ли оператор, который вместо этого делится на ceil? (Я знаю об операторе /, который в Python 3 выполняет разделение с плавающей запятой.)

Ответ 1

Нет оператора, который делит на ceil. Вам нужно import math и использовать math.ceil

Ответ 2

Вы можете просто выполнить перевернутое разделение полов:

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]

Ответ 3

Вы можете сделать (x + (d-1)) // d при делении x на d, т.е. (x + 4) // 5.

Ответ 4

Вы всегда можете просто сделать это inline, а

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

Ответ 5

Обратите внимание, что значение math.ceil ограничено 53 битами точности. Если вы работаете с большими целыми числами, вы не можете получить точные результаты.

gmpy2 libary предоставляет функцию c_div, которая использует потолочное округление.

Отказ от ответственности: я поддерживаю gmpy2.

Ответ 6

Решение 1. Преобразование пола в потолок с отрицанием

def ceiling_division(n, d):
    return -(n // -d)

Напоминающий трюк с левитацией Пенна и Теллера, он "переворачивает мир вверх ногами (с отрицанием), использует разделение на ровные полы (где поменялись местами потолок и пол), а затем переворачивает мир вправо вверх (снова с отрицанием) "

Решение 2: пусть divmod() сделает всю работу

def ceiling_division(n, d):
    q, r = divmod(n, d)
    return q + bool(r)

Функция divmod() дает (a//b, a % b) для целых чисел (это может быть менее надежно с плавающей точкой из-за ошибки округления). Шаг с bool(r) добавляет единицу к частному всякий раз, когда есть ненулевой остаток.

Решение 3. Настройте числитель перед делением

def ceiling_division(n, d):
    return (n + d - 1) // d

Переведите числитель вверх, чтобы деление пола округлилось до предполагаемого потолка. Обратите внимание, это работает только для целых чисел.

Решение 4. Преобразуйте в числа с плавающей запятой, чтобы использовать math.ceil()

def ceiling_division(n, d):
    return math.ceil(n / d)

Код math.ceil() легко понять, но он конвертирует из целых чисел в плавающие и обратно. Это не очень быстро и может иметь проблемы с округлением. Кроме того, он опирается на семантику Python 3, где "истинное деление" создает число с плавающей точкой, а функция ceil() возвращает целое число.

Ответ 7

Я пришел сюда из-за бинарных модульных групп и хотел взаимодействовать с обоими общими серединами списка. Например, [1,2,3,4] имеет 2 и 3.

Для взаимодействия с серединой списка и использования оператора потолка:

foo    = [1,2,3,4]
length = len(foo)
floor  = (len(foo)//2)
ceil   = floor+1
floor == 2 #True
ceil  == 3 #True