我发现了 Python 中的//
运算符,它在 Python 3 中用地板除法。
有没有用 ceil 划分的运算符?(我知道/
Python 3 中进行浮点除法的运算符。)
我发现了 Python 中的//
运算符,它在 Python 3 中用地板除法。
有没有用 ceil 划分的运算符?(我知道/
Python 3 中进行浮点除法的运算符。)
不,但您可以使用倒置的楼层划分:¹
def ceildiv(a, b):
return -(a // -b)
这是有效的,因为Python 的除法运算符执行地板除法(与 C 中的整数除法截断小数部分不同)。
这是一个演示:
>>> from __future__ import division # for Python 2.x compatibility
>>> import math
>>> def ceildiv(a, b):
... return -(a // -b)
...
>>> b = 3
>>> for a in range(-7, 8):
... q1 = math.ceil(a / b) # a/b is float division
... q2 = ceildiv(a, b)
... print("%2d/%d %2d %2d" % (a, b, q1, q2))
...
-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
math.ceil(a / b)
可以悄悄地产生不正确的结果,因为它引入了浮点错误。例如:
>>> from __future__ import division # Python 2.x compat
>>> import math
>>> def ceildiv(a, b):
... return -(a // -b)
...
>>> x = 2**64
>>> y = 2**48
>>> ceildiv(x, y)
65536
>>> ceildiv(x + 1, y)
65537 # Correct
>>> math.ceil(x / y)
65536
>>> math.ceil((x + 1) / y)
65536 # Incorrect!
一般来说,除非您特别需要,否则完全避免浮点运算被认为是一种很好的做法。浮点数学有几个棘手的边缘情况,如果您不密切注意,它们往往会引入错误。在没有硬件 FPU 的小型/低功耗设备上,它的计算成本也可能很高。
¹在此答案的先前版本中, ceildiv 被实施为,return -(-a // b)
但return -(a // -b)
在评论者报告后者在基准测试中表现稍好后更改为。这是有道理的,因为被除数 ( a ) 通常大于除数 ( b )。由于 Python 使用任意精度算术来执行这些计算,因此计算一元否定-a
几乎总是涉及与计算相同或更多的工作-b
。
没有与 ceil 相除的运算符。您需要import math
并使用math.ceil
def ceiling_division(n, d):
return -(n // -d)
让人想起Penn & Teller 悬浮技巧,这“把世界颠倒过来(用否定),使用简单的地板分割(天花板和地板已经交换),然后把世界颠倒过来(再次用否定) "
def ceiling_division(n, d):
q, r = divmod(n, d)
return q + bool(r)
divmod ()函数提供(a // b, a % b)
整数(由于舍入误差,浮点数可能不太可靠)。bool(r)
每当存在非零余数时,步骤 with将商加一。
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()函数返回一个整数。
你可以(x + (d-1)) // d
在除以时x
做d
,例如(x + 4) // 5
。
你也可以随时内联
((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
如果您想将一个数字取消多个。它就像我们在 excel 中有 Math.celling 一样工作。
def excel_celling(number=None, multiple_off=None):
quotient = number // multiple_off
reminder = number % multiple_off
celling_value = quotient * multiple_off + (multiple_off, 0)[reminder==0]
return int(celling_value)
assert excel_celling(99.99, 100) == 100, "True"
print(excel_celling(99.99, 100) , 100)
assert excel_celling(1, 100) == 100, "True"
print(excel_celling(1, 100),100)
assert excel_celling(99, 100) == 100, "True"
print(excel_celling(99, 100),100)
assert excel_celling(90, 100) == 100, "True"
print(excel_celling(90, 100),100)
assert excel_celling(101, 100) == 200, "True"
print(excel_celling(101, 100),200)
assert excel_celling(199, 100) == 200, "True"
print(excel_celling(199, 100),200)
assert excel_celling(199.99, 100) == 200, "True"
print(excel_celling(199.99, 100),200)
assert excel_celling(200, 100) == 200, "True"
print(excel_celling(200, 100),200)
结果
100 100
100 100
100 100
100 100
200 200
200 200
200 200
200 200
简单的解决方案:a // b + 1