파이썬에 // 연산자와 동등한 상한선이 있습니까?


127

//파이썬 3에서 바닥으로 나누는 연산자에 대해 알아 냈습니다 .

대신 ceil로 나누는 연산자가 있습니까? ( /파이썬 3에서 부동 소수점 나누기를 수행 하는 연산자 에 대해 알고 있습니다.)


1
중요 : int 또는 float 결과를 원하십니까?
SMCI

10
dlitz의 수락 된 답변을 변경해야합니다. math.ceil은 부동 소수점 용이며 Python의 임의 정밀도 long int에서는 작동하지 않습니다.
endolith

2
@milllimoose 질문은 유효합니다. 1) "천장 나누기"는 "계수로 나누기"를 기반으로하기 때문입니다. 2) 수학은 실제로 일반적인 것과 그렇지 않은 것을 말하지 않습니다. 3) "연속 빈에이 작업이 필요합니다. 포장 문제 ", 즉 $ n $ 품목을 포장하는 데 필요한 $ k $ 크기의 상자 수.
Tomasz Gandor

답변:


55

ceil로 나누는 연산자가 없습니다. 당신은import math 하고 사용math.ceil


그래서 foobar = math.ceil (foo / bar)? 흠, 난 그와 함께 살 수있다, 나는 그것을 사용하고 싶었 어디 모르겠어요, 덕분에 그냥 궁금했다
Cradam

37
–1을 사용하지 마십시오 . 이것은 매우 큰 정수에 대해 실패하기 시작합니다. 어느와 정수 도메인의 여러 정밀도 연산 라이브러리 또는 숙박이 사용하는 방법.
WIM

5
확실히 정수 영역에 머물러야합니다. 그것은 더 성능이 좋고 두통이 적다는 것을 거의 보장합니다 .
Samy Bencherif

1
@David 天宇 Wong gmpy2 (여기에 다른 답변에서 언급)는 좋습니다.
wim

1
math.ceil은 53 비트의 정밀도로 제한됩니다. 큰 정수로 작업하는 경우 정확한 결과를 얻지 못할 수 있습니다.
techkuz

291

거꾸로 바닥을 나눌 수 있습니다.

def ceildiv(a, b):
    return -(-a // b)

이것은 파이썬의 나누기 연산자가 바닥 나누기를 수행하기 때문에 작동합니다 (정수 나누기가 분수 부분을 자르는 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]

2
@apadana 나는 이것이 매우 영리하지만 읽기 쉽고 유지하기 어렵다는 데 동의합니다! 동료 중 한 명이 내 코드를 읽을 때 코드가 무엇을하는지 이해할 수 있도록 수학에서 ceil을 가져 오기로 결정했습니다!
SlimCheney

2
@apadana 동의하지 않습니다. 이 질문은이 "in"Python에 대한 연산자가 "있는지"물었습니다. 응답에 따르면 대답은 "아니오"로 나타납니다. 그래도 유용성에 대해 dlitz의 답변을 찬성하고 있습니다.
Ana Nimbus

12
@SlimCheney이 방법을 문서화 된 함수에 던져 넣으면 좋습니다. 한 번의 동작으로 성능 + 가독성.
Samy Bencherif

2
@SamyBencherif : 성능 + 가독성뿐만 아니라 대규모 입력에 대한 정확성도 있습니다. 부동 소수점에는 표현 제한이 있지만 Python은 int그렇지 않으며 (의미있는 것은 없습니다. 64 비트 Python에서는 30 * (2**63 - 1)비트 수로 제한됩니다 ) 일시적으로로 변환해도 float정보가 손실 될 수 있습니다. 비교 math.ceil((1 << 128) / 10)-(-(1 << 128) // 10).
ShadowRanger

1
이것은 표준 라이브러리에 포함되어야합니다
endolith

26

당신이 할 수있는 (x + (d-1)) // d나눔 경우 xd(x + 4) // 5.


2
이것은 내가 영원히 사용했던 고전적인 방법입니다. 하지만 음수 제수에는 작동하지 않습니다.
Mark Ransom 2013

와 동일한 결과 를 생성합니다 math.ceil().
Abhijeet

3
@Abhijeet 예, 그것이 질문이 묻는 것입니다. 위의 큰 정수에서 더 잘 작동한다는 점을 제외하고 sys.float_info.max는 가져 오기가 필요하지 않습니다.
Artyer

23

솔루션 1 : 부정을 사용하여 바닥을 천장으로 변환

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

Penn & Teller 부상 트릭을 연상시킵니다. 이 "세계를 거꾸로 (부정으로) 뒤집고 (천장과 바닥이 바뀐) 일반 바닥 분할을 사용한 다음, 세계를 오른쪽으로 뒤집습니다 (다시 부정으로). "

솔루션 2 : divmod ()가 작업을 수행하도록합니다.

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

divmod () 함수를 제공한다 (a // b, a % b)(이 때문에 반올림 오차 수레 안정성이 낮을 수있다)에 대해 정수. 이 단계 bool(r)는 0이 아닌 나머지가있을 때마다 몫에 1을 더합니다.

해결 방법 3 : 나누기 전에 분자 조정

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

분자를 위쪽으로 이동하여 바닥 분할이 의도 한 천장으로 내림되도록합니다. 이것은 정수에서만 작동합니다.

해결 방법 4 : math.ceil ()을 사용하기 위해 float로 변환

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

math.ceil () 코드는 이해하기 쉬운,하지만 수레와 위로의 int로 변환합니다. 이것은 매우 빠르지 않으며 반올림 문제가있을 수 있습니다. 또한 "true division"이 float를 생성하고 ceil () 함수가 정수를 반환하는 Python 3 의미 체계에 의존 합니다.


2
빠른 테스트에서 # 1은 -(-a // b)o_O
endolith

여기 에서 -(a // -b)보다 빠른 확인 -(-a // b), 적어도 타이밍 장난감 예제python -m timeit ...
Jasha

19

항상 인라인으로 할 수 있습니다.

((foo - 1) // bar) + 1

python3에서 이것은 속도에 관심이 있다면 float 분할을 강제하고 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

방금 테스트를 직접 실행했습니다. 약 12.5 초가 걸립니다. 음, 속도가 그렇게 큰데 왜 속도에 신경 쓰지 않겠습니까?
Cradam

3
@Cradam 그는 1 억 호출 ( number=100000000)을 사용하고 있습니다. 단일 호출 당 차이는 거의 없습니다.
Rushy Panchal 2013

4
코드 명확성이 모든 것을 우선시하기 때문입니다. 이 경우 명확성은 아마도 객관적입니다. 그러나 항상 먼저 읽기 / 유지 관리가 가능해야합니다. 성능 체크 포인트를 발견 한 경우에만 규칙을 어길 수 있습니다. 현대 기계는 매우 빠르며 프로그램이 수행하는 다른 모든 작업이 이러한 종류의 차이를 노이즈로 인해 손실되는 경우가 많습니다.
Travis Griggs 2013

6
부동 소수점 수학 대신 정수 수학을 사용하는 @TravisGriggs는 속도만을위한 것이 아닙니다. 충분히 큰 정수의 경우 부동 소수점 수학은 오답 제공
endolith

1
경우 foo = -8bar = -4, 예를 들어, 대답은 추천하지 3,해야한다 -8 // -4. 파이썬 바닥 나누기는 "결과에 '바닥'함수를 적용한 수학적 나누기" 로 정의되며 천장 나누기는 동일하지만 ceil()대신 floor().
endolith

8

math.ceil은 53 비트의 정밀도로 제한됩니다. 큰 정수로 작업하는 경우 정확한 결과를 얻지 못할 수 있습니다.

gmpy2의 libary가 제공 c_div천장 라운딩을 사용 기능.

면책 조항 : gmpy2를 유지합니다.


3
이 패키지는 내가 수학이나 과학에 중점을 둔 일을하는 경우 유용 할 것입니다. 그래도 핵심 라이브러리를 사용하는 답변을 선호합니다. 나는 그것이 유용한 답변 그대로 불구하고 upvote에를주고있다
Cradam

와, 확인할 수 있습니다. python2 -c 'from math import ceil;assert ceil(11520000000000000102.9)==11520000000000000000'(뿐만 아니라 대체 python3) 둘 다True
JamesTheAwesomeDude jul.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.