2010-05-08 57 views
6

Có cách nào để lấy ceil có độ chính xác cao trong thập phân không?nhận Ceil() của thập phân trong python?

>>> import decimal; 
>>> decimal.Decimal(800000000000000000001)/100000000000000000000 
Decimal('8.00000000000000000001') 
>>> math.ceil(decimal.Decimal(800000000000000000001)/100000000000000000000) 
8.0 

toán viên đạn giá trị và trả về giá trị không chính xác

+0

Tôi mới bắt đầu với python, chỉ mới bắt đầu vào ngày hôm qua. Stumbled khi vấn đề này trong chương trình thực hành thứ hai của tôi (đầu tiên là tất nhiên bắt buộc "in" Hello, World! '; "). vì vậy, tôi thấy khó khăn để đánh giá câu trả lời tốt nhất cho điều này. Giải pháp decimal.Context của Matthew Flaschen đã làm việc trong trường hợp cụ thể của tôi. Nhưng tôi muốn những người khác đề cao giải pháp tốt nhất (cũng sẽ hữu ích cho những người mới như tôi có thể giải thích tại sao một phương pháp nào đó hoạt động tốt hơn) và tôi sẽ quay lại và chấp nhận. – Gunjan

Trả lời

5
x = decimal.Decimal('8.00000000000000000000001') 
with decimal.localcontext() as ctx: 
    ctx.prec=100000000000000000 
    ctx.rounding=decimal.ROUND_CEILING 
    y = x.to_integral_exact() 
+4

Điều này là tốt, nhưng không cần phải thay đổi độ chính xác ngữ cảnh tại đây. 'to_integral_exact' cũng nhận một tham số' làm tròn', vì vậy bạn có thể tránh rối tung hoàn toàn với bối cảnh. –

3

Bạn có thể làm điều này bằng cách sử dụng chính xác và làm tròn tùy chọn chế độ của các nhà xây dựng bối cảnh.

ctx = decimal.Context(prec=1, rounding=decimal.ROUND_CEILING) 
ctx.divide(decimal.Decimal(800000000000000000001), decimal.Decimal(100000000000000000000)) 

EDIT: Bạn nên xem xét thay đổi câu trả lời chấp nhận .. Mặc dù prec có thể tăng lên khi cần thiết, to_integral_exact là một giải pháp đơn giản hơn.

+0

hoàn hảo :) --- hoàn thành giới hạn ký tự --- – Gunjan

+2

@Gunjan, nếu nó hoàn hảo, tại sao không chấp nhận nó ?! –

+0

@Alex xin lỗi đã phải rời khỏi trước thời gian chờ 6 phút. Cảm ơn lời nhắc – Gunjan

0
>>> decimal.Context(rounding=decimal.ROUND_CEILING).quantize(
... decimal.Decimal(800000000000000000001)/100000000000000000000, 0) 
Decimal('9') 
+0

Lưu ý rằng giải pháp này có vấn đề đối với các phiên bản 'thập phân 'có giá trị lớn: ví dụ, nếu bạn thử' c.quantize (decimal.Decimal (' 1e100 '), 1) 'với ngữ cảnh' c', bạn sẽ nhận được một 'InvalidOperation' ngoại lệ. –

0
def decimal_ceil(x): 
    int_x = int(x) 
    if x - int_x == 0: 
     return int_x 
    return int_x + 1 
18

Cách trực tiếp nhất để có những trần của một trường hợp Decimal x là sử dụng x.to_integral_exact(rounding=ROUND_CEILING). Không cần phải gây rối với bối cảnh ở đây. Lưu ý rằng điều này đặt các cờ InexactRounded khi thích hợp; nếu bạn không muốn chạm cờ, hãy sử dụng x.to_integral_value(rounding=ROUND_CEILING) để thay thế. Ví dụ:

>>> from decimal import Decimal, ROUND_CEILING 
>>> x = Decimal('-123.456') 
>>> x.to_integral_exact(rounding=ROUND_CEILING) 
Decimal('-123') 

Không giống như hầu hết các phương pháp số thập phân, các to_integral_exactto_integral_value phương pháp này không bị ảnh hưởng bởi độ chính xác của bối cảnh hiện nay, vì vậy bạn không cần phải lo lắng về việc thay đổi chính xác:

>>> from decimal import getcontext 
>>> getcontext().prec = 2 
>>> x.to_integral_exact(rounding=ROUND_CEILING) 
Decimal('-123') 

Nhân tiện, trong Python 3.x, math.ceil hoạt động chính xác như bạn muốn, ngoại trừ việc nó trả về int thay vì một ví dụ Decimal. Điều đó hoạt động vì math.ceil có thể quá tải đối với các kiểu tùy chỉnh trong Python 3. Trong Python 2, math.ceil chỉ cần chuyển đổi cá thể Decimal thành float trước tiên, có khả năng mất thông tin trong quá trình, để bạn có thể kết quả không chính xác.

+0

Chỉ cần cho đầy đủ: trong python 2.x 'math.ceil' không hoạt động như mong đợi: nó chuyển đổi thập phân sang phao trước. Do đó 'int (ceil (D ('1.0000000000000001')))' đánh giá 1 trong python 2.x và 2 trong python 3.x –

+0

@AntonyHatchkins: Cảm ơn, điểm tốt. Tôi đã chỉnh sửa thông tin đó vào câu trả lời. –

0

Chỉ cần sử dụng hiệu lực để thực hiện việc này. nhập toán

def lo_ceil(num, potency=0): # Use 0 for multiples of 1, 1 for multiples of 10, 2 for 100 ... 
     n = num/(10.0 ** potency) 
     c = math.ceil(n) 
     return c * (10.0 ** potency) 

lo_ceil(8.0000001, 1) # return 10 
Các vấn đề liên quan