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

Cra*_*dam 95 python python-3.x

我发现了//Python中的运算符,它在Python 3中与floor进行了划分.

是否有运营商与ceil分开?(我知道/在Python 3中进行浮点除法的运算符.)

dli*_*itz 248

你可以做颠倒的地板部门:

def ceildiv(a, b):
    return -(-a // b)
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为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]
Run Code Online (Sandbox Code Playgroud)

  • @SlimCheney把这个方法扔进一个记录的函数中,你很高兴.一次扫描中的性能+可读性. (8认同)
  • @apadana 我不同意。问题询问是否有这个“在”Python 中的运算符。根据回答,答案似乎是否定的。不过,我对 dlitz 的有用性表示赞赏。 (3认同)
  • @apadana我同意这很聪明,但不是很易读,也很难维护!我已经决定从数学中导入ceil,以便当我的一位同事阅读我的代码时,他会理解它的作用! (2认同)
  • @SamyBencherif:不仅仅是性能+可读性,还有大输入的正确性;浮点数有表示限制,而 Python 的 `int` 则没有(好吧,没有任何意义;在 64 位 Python 上,您仅限于 `30 * (2**63 - 1)` 位数字),甚至可以暂时转换为`float` 可能会丢失信息。将 `math.ceil((1 << 128) / 10)` 与 `-(-(1 << 128) // 10)` 进行比较。 (2认同)
  • 这应该只包含在标准库中 (2认同)
  • 对于紧凑版本:`ceildiv = lambda a, b: -(-a // b)` (2认同)

Cha*_*via 50

没有运营商与ceil分开.你需要import math和使用math.ceil

  • -1**不使用**,对于非常大的整数,这将开始失败.使用多精度算术库或使用[this](/sf/answers/1225793901/)方法保留整数域. (25认同)
  • 绝对留在整数域中。几乎可以保证性能更高,头痛也更少。 (4认同)
  • 请注意,math.ceil 的精度限制为 53 位。如果您使用大整数,则可能无法获得准确的结果。 (2认同)

pok*_*oke 21

你可以做(x + (d-1)) // d划分时x通过d,即(x + 4) // 5.

  • @Abhijeet 是的,这就是问题所在。除了它对高于 `sys.float_info.max` 的大整数效果更好,并且不需要导入。 (3认同)
  • 这是我一直使用的经典方法。但不适用于负除数。 (2认同)

Tra*_*ggs 17

你也可以随便进行内联

((foo - 1) // bar) + 1
Run Code Online (Sandbox Code Playgroud)

在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
Run Code Online (Sandbox Code Playgroud)

  • 因为代码清晰度胜过所有.在这种情况下,清晰度可能是客观的.但是你应该首先使可读/可维护.当且仅当您发现性能检查点时,您是否违反了规则.现代机器是如此之快,所以你的程序正在做的所有其他东西往往会使噪音中的这种差异丢失. (4认同)
  • @TravisGriggs使用整数数学而不是浮点数学不仅仅是为了速度.对于足够大的整数,浮动数学会给出错误的答案 (4认同)
  • @Cradam请注意,他正在使用1亿次调用​​(`number = 100000000`).每次通话,差异是非常微不足道的. (2认同)

Ray*_*ger 10

解决方案1:通过求反将地板转换为天花板

def ceiling_division(n, d):
    return -(n // -d)
Run Code Online (Sandbox Code Playgroud)

让人联想到Penn&Teller的悬浮技巧,“将世界颠倒(带负号),使用普通地板分隔(将天花板和地板交换了),然后使世界朝上(带负号)。 ”

解决方案2:让divmod()完成工作

def ceiling_division(n, d):
    q, r = divmod(n, d)
    return q + bool(r)
Run Code Online (Sandbox Code Playgroud)

所述divmod()函数给出(a // b, a % b)为整数(这可能是用浮漂较不可靠,由于舍入误差)。bool(r)每当存在非零余数时,带有的步骤会将商加1。

解决方案3:在除法之前调整分子

def ceiling_division(n, d):
    return (n + d - 1) // d
Run Code Online (Sandbox Code Playgroud)

向上平移分子,以便将楼层划分向下舍入到所需的上限。注意,这仅适用于整数。

解决方案4:转换为浮点数以使用math.ceil()

def ceiling_division(n, d):
    return math.ceil(n / d)
Run Code Online (Sandbox Code Playgroud)

math.ceil()代码很容易理解,但它从整数到彩车和背部转换。这不是很快,并且可能存在舍入问题。而且,它依赖于Python 3语义,其中“真除法”产生浮点,而ceil()函数返回整数。

  • 在快速测试中,#1 是最快的,甚至与 `-(-a // b)` o_O 相比也是如此 (3认同)

cas*_*evh 8

请注意,math.ceil限制为53位精度.如果您正在使用大整数,则可能无法获得准确的结果.

所述gmpy2 libary提供一种c_div它采用天花板的舍入函数.

免责声明:我维持gmpy2.

  • 如果我从事数学或科学方面的工作,这个软件包会很有用,我更喜欢使用核心库的答案.我给了一个upvote,因为这是一个有用的答案 (3认同)