在 Python 中是否有相当于 // 运算符的上限?

新手上路,请多包涵

我在 Python 中发现了 // 运算符,它在 Python 3 中用 floor 进行除法。

有没有用 ceil 代替的运算符? (我知道 / 运算符,它在 Python 3 中进行浮点除法。)

原文由 Cradam 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 392
2 个回答

没有除以 ceil 的运算符。您需要 import math 并使用 math.ceil

原文由 Charles Salvia 发布,翻译遵循 CC BY-SA 4.0 许可协议

不,但您可以使用倒置地板划分:¹

 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?

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 涉及更多或更多的工作。

原文由 dlitz 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题