Tôi đã tìm hiểu về //
toán tử trong Python mà trong Python 3 thực hiện phép chia với tầng.
Có toán tử nào phân chia bằng ceil không? (Tôi biết về /
toán tử mà trong Python 3 thực hiện phép chia dấu phẩy động.)
Tôi đã tìm hiểu về //
toán tử trong Python mà trong Python 3 thực hiện phép chia với tầng.
Có toán tử nào phân chia bằng ceil không? (Tôi biết về /
toán tử mà trong Python 3 thực hiện phép chia dấu phẩy động.)
Câu trả lời:
Không có toán tử nào phân chia bằng ceil. Bạn cần import math
và sử dụngmath.ceil
Bạn chỉ có thể thực hiện chia tầng lộn ngược:
def ceildiv(a, b):
return -(-a // b)
Điều này hoạt động vì toán tử phân chia của Python thực hiện phân chia tầng (không giống như trong C, trong đó phép chia số nguyên cắt ngắn phần phân số).
Điều này cũng hoạt động với các số nguyên lớn của Python, vì không có chuyển đổi dấu phẩy động (mất mát).
Đây là một minh chứng:
>>> 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
thì không (tốt, không có ý nghĩa nào; trên Python 64 bit, bạn bị giới hạn ở 30 * (2**63 - 1)
số bit), và thậm chí chuyển đổi tạm thời float
có thể làm mất thông tin. So sánh math.ceil((1 << 128) / 10)
với -(-(1 << 128) // 10)
.
Bạn có thể làm (x + (d-1)) // d
khi chia x
cho d
, tức là (x + 4) // 5
.
math.ceil()
.
sys.float_info.max
và nó không yêu cầu nhập.
def ceiling_division(n, d):
return -(n // -d)
Gợi nhớ đến thủ thuật bay lên của Penn & Teller , trò chơi này "lật ngược thế giới (với phủ định), sử dụng phân chia tầng đơn giản (nơi trần và sàn đã được hoán đổi), sau đó lật ngược thế giới lên (với phủ định lại) "
def ceiling_division(n, d):
q, r = divmod(n, d)
return q + bool(r)
Hàm divmod () cung cấp (a // b, a % b)
cho các số nguyên (điều này có thể kém tin cậy hơn với các float do lỗi làm tròn). Bước với bool(r)
thêm một vào thương bất cứ khi nào có phần dư khác 0.
def ceiling_division(n, d):
return (n + d - 1) // d
Dịch tử số lên trên để phân chia tầng làm tròn xuống trần dự định. Lưu ý, điều này chỉ hoạt động đối với số nguyên.
def ceiling_division(n, d):
return math.ceil(n / d)
Mã math.ceil () rất dễ hiểu, nhưng nó chuyển đổi từ ints thành float và back. Quá trình này diễn ra không nhanh và có thể có vấn đề làm tròn. Ngoài ra, nó dựa trên ngữ nghĩa Python 3 trong đó "phân chia thực sự" tạo ra một float và trong đó hàm ceil () trả về một số nguyên.
-(-a // b)
o_O
-(a // -b)
là nhanh hơn -(-a // b)
, ít nhất là khi tính thời gian các ví dụ đồ chơi vớipython -m timeit ...
Bạn luôn có thể làm điều đó trong dòng
((foo - 1) // bar) + 1
Trong python3, đây chỉ là một thứ tự cường độ nhanh hơn so với việc buộc phân chia float và gọi ceil (), miễn là bạn quan tâm đến tốc độ. Điều bạn không nên làm, trừ khi bạn đã chứng minh thông qua việc sử dụng rằng bạn cần phải làm như vậy.
>>> 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
). Mỗi cuộc gọi, sự khác biệt là khá không đáng kể.
foo = -8
và bar = -4
, câu trả lời phải là 2, không phải 3, giống như -8 // -4
. Phân chia tầng trong Python được định nghĩa là "phân chia toán học với hàm 'sàn' được áp dụng cho kết quả" và phân chia trần là điều tương tự nhưng với ceil()
thay vì floor()
.
Lưu ý rằng math.ceil được giới hạn ở độ chính xác 53 bit. Nếu bạn đang làm việc với các số nguyên lớn, bạn có thể không nhận được kết quả chính xác.
Các gmpy2 THƯ VIỆN cung cấp một c_div
chức năng trong đó sử dụng trần tròn.
Tuyên bố từ chối trách nhiệm: Tôi duy trì gmpy2.
python2 -c 'from math import ceil;assert ceil(11520000000000000102.9)==11520000000000000000'
(cũng như thay thế python3
) Cả hai đềuTrue
Giải pháp đơn giản: a // b + 1