Saya mengetahui tentang //
operator dengan Python yang dalam Python 3 melakukan pembagian dengan lantai.
Apakah ada operator yang membagi dengan ceil? (Saya tahu tentang /
operator yang dalam Python 3 melakukan pembagian floating point.)
Saya mengetahui tentang //
operator dengan Python yang dalam Python 3 melakukan pembagian dengan lantai.
Apakah ada operator yang membagi dengan ceil? (Saya tahu tentang /
operator yang dalam Python 3 melakukan pembagian floating point.)
Jawaban:
Tidak ada operator yang membagi dengan langit-langit. Anda perlu import math
dan menggunakanmath.ceil
Anda bisa melakukan pembagian lantai terbalik:
def ceildiv(a, b):
return -(-a // b)
Ini berfungsi karena operator divisi Python melakukan pembagian lantai (tidak seperti di C, di mana pembagian integer memotong bagian pecahan).
Ini juga berfungsi dengan bilangan bulat besar Python, karena tidak ada konversi floating-point (lossy).
Berikut peragaannya:
>>> 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]
int
tidak (yah, tidak ada yang berarti; pada Python 64 bit Anda terbatas pada 30 * (2**63 - 1)
angka bit), dan bahkan untuk sementara mengonversi float
dapat kehilangan informasi. Bandingkan math.ceil((1 << 128) / 10)
dengan -(-(1 << 128) // 10)
.
Anda bisa melakukannya (x + (d-1)) // d
saat membagi x
dengan d
, yaitu (x + 4) // 5
.
math.ceil()
.
sys.float_info.max
, dan itu tidak memerlukan impor.
def ceiling_division(n, d):
return -(n // -d)
Mengingatkan pada trik levitasi Penn & Teller , ini "membalikkan dunia (dengan negasi), menggunakan pembagian lantai biasa (di mana langit-langit dan lantai telah ditukar), dan kemudian membalikkan dunia ke kanan (dengan negasi lagi) "
def ceiling_division(n, d):
q, r = divmod(n, d)
return q + bool(r)
Fungsi divmod () diberikan (a // b, a % b)
untuk integer (ini mungkin kurang dapat diandalkan dengan float karena kesalahan round-off). Langkah dengan bool(r)
menambahkan satu ke hasil bagi setiap kali ada sisa bukan nol.
def ceiling_division(n, d):
return (n + d - 1) // d
Terjemahkan pembilangnya ke atas sehingga pembagian lantai membulat ke bawah ke langit-langit yang diinginkan. Catatan, ini hanya berfungsi untuk bilangan bulat.
def ceiling_division(n, d):
return math.ceil(n / d)
Kode math.ceil () mudah dimengerti, tetapi diubah dari int menjadi floats dan back. Ini tidak terlalu cepat dan mungkin memiliki masalah pembulatan. Juga, ini bergantung pada semantik Python 3 di mana "pembagian benar" menghasilkan pelampung dan di mana fungsi ceil () mengembalikan bilangan bulat.
-(-a // b)
o_O
-(a // -b)
lebih cepat dari -(-a // b)
, setidaknya ketika contoh mainan waktu denganpython -m timeit ...
Anda juga selalu dapat melakukannya secara inline
((foo - 1) // bar) + 1
Dalam python3, ini hanya malu urutan besarnya lebih cepat daripada memaksa divisi float dan memanggil ceil (), asalkan Anda peduli dengan kecepatan. Yang seharusnya tidak Anda lakukan, kecuali Anda telah membuktikan melalui penggunaan yang Anda perlukan.
>>> timeit.timeit("((5 - 1) // 4) + 1", number = 100000000)
1.7249219375662506
>>> timeit.timeit("ceil(5/4)", setup="from math import ceil", number = 100000000)
12.096064013894647
number=100000000
). Per satu panggilan, perbedaannya tidak terlalu signifikan.
foo = -8
dan bar = -4
, misalnya, jawabannya harus 2, bukan 3, sama seperti -8 // -4
. Pembagian lantai Python didefinisikan sebagai "bahwa pembagian matematika dengan fungsi 'lantai' diterapkan pada hasil" dan pembagian langit-langit adalah hal yang sama tetapi ceil()
bukan dengan floor()
.
Perhatikan bahwa math.ceil dibatasi hingga 53 bit presisi. Jika Anda bekerja dengan bilangan bulat besar, Anda mungkin tidak mendapatkan hasil yang tepat.
The gmpy2 libary menyediakan c_div
fungsi yang menggunakan langit-langit pembulatan.
Penafian: Saya mempertahankan gmpy2.
python2 -c 'from math import ceil;assert ceil(11520000000000000102.9)==11520000000000000000'
(dan juga menggantikannya python3
) KEDUATrue
Solusi sederhana: a // b + 1