Я дізнався про //
оператора в Python, який в Python 3 робить поділ з підлогою.
Чи є натомість оператор, який ділиться з ceil? (Я знаю про /
оператора, який в Python 3 робить поділ з плаваючою комою.)
Я дізнався про //
оператора в Python, який в Python 3 робить поділ з підлогою.
Чи є натомість оператор, який ділиться з ceil? (Я знаю про /
оператора, який в Python 3 робить поділ з плаваючою комою.)
Відповіді:
Немає жодного оператора, який ділиться зі стелею. Вам потрібно 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
.
math.ceil()
.
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 () легко зрозуміти, але він перетворюється з ints у плаваючі та назад. Це не дуже швидко, і це може мати проблеми з округленням. Крім того, він спирається на семантику Python 3, де "справжній поділ" створює float і де функція 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 визначається як "поділ математичного поділу з функцією" floor ", застосованою до результату", а поділ на стелі - це те саме, але ceil()
замість цього floor()
.
Зауважте, що math.ceil обмежений 53 бітами точності. Якщо ви працюєте з великими цілими числами, ви можете не отримати точних результатів.
Gmpy2 libary забезпечує c_div
функцію , яка використовує стельове округлення.
Відмова: Я підтримую gmpy2.
python2 -c 'from math import ceil;assert ceil(11520000000000000102.9)==11520000000000000000'
(а також заміщення python3
) True
Просте рішення: a // b + 1