Pythonには//演算子に相当する上限がありますか?


127

//Python 3で床で除算を行うPython の演算子について知りました。

代わりにceilで割る演算子はありますか?(/Python 3で浮動小数点除算を行う演算子について知っています。)


1
重要:intまたはfloatの結果が必要ですか?
smci 2015年

10
受け入れられた回答をdlitzに変更する必要があります。math.ceilは浮動小数点数用で、Pythonの任意精度のlong intでは機能しません。
内部石2016年

2
@milllimoose質問は有効です。1) "ceil除算"も "係数による除算"に基づいているため、2)数学は実際には何が一般的で何がそうでないかを述べていない、3) "連続ビンにこの操作が必要です梱包の問題」、つまり$ n $のアイテムを梱包するために$ k $サイズの箱がいくつ必要か。
Tomasz Gandor

回答:


55

ceilで割る演算子はありません。あなたがする必要がimport mathありますmath.ceil


だからfoobar = math.ceil(foo / bar)?うーん、私はそれと一緒に暮らすことができ、どこでそれを使いたかったのかわからない、ちょうど好奇心旺盛でした、ありがとう
Cradam

37
–1 はを使用しないでください。これは、非常に大きな整数では失敗し始めます。このアプローチでは、倍精度算術ライブラリーを使用するか、整数領域にとどまります。
2017年

5
間違いなく整数ドメインにとどまる。パフォーマンスが向上、頭痛の種が少ないことがほぼ保証されています。
Samy Bencherif 2018

1
@David天宇Wong gmpy2(ここの別の回答で言及)は良いです。
WIM

1
math.ceilは53ビットの精度に制限されていることに注意してください。大きな整数で作業している場合、正確な結果が得られない可能性があります。
techkuz

290

床を逆さまに分割するだけです。

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]

2
@apadana私はこれがとても賢いのに同意しますが、とても読みやすく、維持するのが難しいです!私は数学からceilをインポートすることにしました。私の同僚の1人が私のコード行を読んだときに、彼がそれが何をするのか理解できるようにするためです!
SlimCheney

2
@apadana同意しない。この「Python」の演算子には「ある」かどうかという質問がありました。回答によると、回答は「いいえ」のようです。しかし、私はその有用性のためにdlitzの答えを支持しています。
Ana Nimbus

12
@SlimCheneyこのメソッドをドキュメント化された関数にトスすれば、準備は完了です。パフォーマンス+読みやすさを一気に。
Samy Bencherif 2018

2
@SamyBencherif:パフォーマンス+読みやすさだけでなく、大規模な入力に対する正確さ。浮動小数点には表現の制限がありますが、Pythonにintはありません(まあ、意味のあるものはありません。64ビットPythonでは、30 * (2**63 - 1)ビット数にます)float。一時的に変換しても、情報が失われる可能性があります。と比較math.ceil((1 << 128) / 10)してください-(-(1 << 128) // 10)
ShadowRanger

1
これは標準ライブラリに含まれている必要があります
エンドリス

26

つまり(x + (d-1)) // d、で除算xするときに行うことができます。d(x + 4) // 5


2
これは私がずっと使ってきた古典的な方法です。ただし、負の除数には機能しません。
Mark Ransom 2013

同じ結果になりmath.ceil()ます。
Abhijeet 2017年

3
@Abhijeetはい、それが質問です。ただしsys.float_info.max、上記の大きな整数の場合はうまく機能し、インポートは必要ありません。
Artyer

22

解決策1:否定を使用して床を天井に変換する

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

ペン&テラー浮上トリックを連想させる、これは「世界を上下逆さまにして(否定で)、単純な床分割を使用し(天井と床が入れ替わっている)、次に世界を逆さまに(否定で)します。 」

解決策2:divmod()に処理を任せる

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

divmod()関数は、与えられる(a // b, a % b)(これが原因丸め誤差にフロートと信頼性の低い場合もある)の整数のため。のステップでbool(r)は、ゼロ以外の剰余がある場合は常に商に1を加えます。

解決策3:除算の前に分子を調整する

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

分子を上に移動して、床の分割が意図した天井に切り捨てられるようにします。これは整数に対してのみ機能することに注意してください。

解決策4:math.ceil()を使用するように浮動小数点に変換する

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

math.ceil()のコードは、理解しやすいですが、それは山車と背中にint型に変換します。これは非常に高速ではなく、丸めの問題がある可能性があります。また、「真の除算」が浮動小数点数を生成し、ceil()関数が整数を返すPython 3のセマンティクスに依存しています。


2
クイックテストでは、-(-a // b)o_O
endolith

少なくともでおもちゃの例のタイミングを調整-(a // -b)する場合-(-a // b)、ここよりも速いことを確認python -m timeit ...
Jasha

19

あなたはいつもそれをインラインで行うこともできます

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

python3では、速度を気にしていれば、float除算を強制してceil()を呼び出すよりも1桁速くなります。使用する必要があることが証明されていない限り、どちらを使用しないでください。

>>> 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 2013

3
@Cradam彼は1億回の呼び出しを行っていることに注意してください(number=100000000)。1回の呼び出しあたり、その差はごくわずかです。
Rushy Panchal 2013

4
コードの明快さがすべてに勝るからです。この場合、おそらく明確さが客観的です。ただし、常に最初に読み取り可能/保守可能にする必要があります。パフォーマンスチェックポイントを発見したときに、ルールを破るのはいつですか。最近のマシンは非常に高速であり、プログラムが実行している他のすべてのことは、この種の違いをノイズで失わせることがよくあります。
Travis Griggs 2013

6
浮動小数点演算の代わりに整数演算を使用する@TravisGriggsは、速度だけではありません。十分に大きな整数の場合、浮動小数点演算は間違った答えを出します
エンドリス2016年

1
場合foo = -8bar = -4、例えば、答えは同じように、2、3ないでなければなりません-8 // -4。Pythonの床除算は、「結果に「floor」関数が適用された数学的除算の除算」として定義され、天井除算は同じですが、ceil()ではありませんfloor()

8

math.ceilは53ビットの精度に制限されていることに注意してください。大きな整数で作業している場合、正確な結果が得られない可能性があります。

gmpy2の libaryが提供c_div天井丸めを使用する関数を。

免責事項:私はgmpy2を維持します。


3
このパッケージは、数学や科学に重点を置いた何かをしている場合に役立ちますが、コアライブラリを使用する答えを好みます。有用な回答なので、私は
賛成票を差し上げてい

うわー、確認できます。python2 -c 'from math import ceil;assert ceil(11520000000000000102.9)==11520000000000000000'(および同様にpython3True
どちら

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.