2010-05-08 20 views
6

Python'da yüksek hassasiyetli bir asma tavan elde etmek için bir yol var mı?python'da Ceil() Ondalık mı alıyorsunuz?

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

matematik değerini yuvarlar ve

+0

Python'da yeni yaşıyorum, aslında dün başladım. İkinci uygulama programımda bu problemin üzerine tökezledim (birincisi zorunlu olan "baskı" Merhaba, Dünya! ";). Bu yüzden, buna en iyi cevabı yargılamak zor. Matthew Flaschen'ın decimal.Context çözümü benim özel durumumda çalıştı. Ama diğerlerinin en iyi çözümü desteklemesini istiyorum (eğer neden belirli bir yaklaşımın daha iyi çalıştığını açıklayabilirseniz benim gibi yeni başlayanlar için de yararlı olabilir) ve geri dönüp kabul edeceğim. – Gunjan

cevap

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

Bu iyi, ancak burada bağlam hassasiyetini değiştirmeye gerek yok. 'to_integral_exact' ayrıca bir 'yuvarlama' argümanını alır, böylece bağlamla bütünleşmekten kaçınabilirsiniz. –

3

Sen hassas kullanarak ve Bağlam yapıcısının modu seçeneğini yuvarlama yapabilirsiniz olmayan kesin bir değer döndürür.

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

DÜZENLEME: Gerektiğinde prec artmış olmasına rağmen sen .. kabul cevabı değiştirmeyi düşünmelisiniz, to_integral_exact daha basit bir çözümdür.

+0

mükemmel :) --- karakter sınırını tamamlıyor --- – Gunjan

+2

@Gunjan, eğer mükemmelse, neden kabul etmiyorsun ?! –

+0

@Alex özür dilerim, 6 dakika zaman aşımından önce ayrılmak zorunda kaldı. Hatırlatıcı – Gunjan

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

Bu çözümün, "Ondalık" örnekleri için büyük bir değere sahip olduğunu unutmayın: örneğin, c.quantize (decimal.Decimal ('1e100'), 1) 'ifadesini 'c' ile denerseniz, bir 'Geçersizİşlem 'istisnası. –

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

bir ondalık örneğinin x tavan almaya en doğrudan yolu x.to_integral_exact(rounding=ROUND_CEILING) kullanmaktır. Buradaki bağlamı karıştırmaya gerek yok. Bu, uygun olduğunda Inexact ve Rounded bayraklarını ayarlar; bayrakların dokunulmasını istemiyorsanız, bunun yerine x.to_integral_value(rounding=ROUND_CEILING) kullanın. Örnek:

Ondalık yöntemlerin çoğu aksine
>>> from decimal import Decimal, ROUND_CEILING 
>>> x = Decimal('-123.456') 
>>> x.to_integral_exact(rounding=ROUND_CEILING) 
Decimal('-123') 

, to_integral_exact ve to_integral_value yöntemleri geçerli bağlamda hassasiyeti etkilenmez, bu nedenle değişen hassasiyet konusunda endişelenmenize gerek yoktur:

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

Bu arada, Python 3.x içinde, math.ceil tam olarak istediğiniz gibi çalışır, ancak bir Decimal örneği yerine bir int döndürür. Bu, Python 3'teki özel türler için math.ceil özel türlerinden yüklenemediği için çalışır. Python 2, math.ceil ilk olarak,örneğini bir float örneğine dönüştürür, potansiyel olarak işlemdeki bilgileri kaybeder, böylece yanlış sonuçlarla sonuçlanabilirsiniz.

+0

Sadece tamlık için: python 2.x 'math.Ceil beklendiği gibi çalışmaz: ilk önce yüzdelik değeri dönüştürür. Bundan dolayı int (ce (D ('1.0000000000000001'))) python 2.x'te 1 ve python'da 2'ye değerlendirir. 3.x –

+0

@AntonyHatchkins: Teşekkürler, iyi bir nokta. Bu bilgiyi cevaba yazdım. –

0

Bunu yapmak için sadece gücü kullanın. import math

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