2010-12-02 11 views
6

ben gitmek istiyorum numaraları var:Hızlı Yolu yakın 5/100ths yuvarlanacak

1.215145156155 => 1.2 
1.368161685161 => 1.35 
1.578414616868 => 1.6 

(* Not:. O sıfırsa salise yer işaretlenmemelidir)

Bunu yapmak için en hızlı yolu nedir?

Bu şu anda ne var olduğunu ve yeterince hızlı değil:

def rounder(v): 
    v = str(round(float(v),2)) 
    if len(v) == 3: v = v + str(0) 
    d0 = int(v[0])#ones 
    d1 = int(v[2])#tenths 
    d2 = int(v[3])#hundredths 
    if d2 <= 4: 
     return str(d0)+'.'+str(d1) 
    elif 4 < d2 < 7: 
     return str(d0)+'.'+str(d1)+str(5) 
    elif d2 >= 7: 
     if d1 != 9: 
      return str(d0)+'.'+str(d1+1) 
     if d1 == 9: 
      return str(d0+1)+'.'+str(0) 

cevap

11

Ölçek, yuvarlak, unscale.

round(20*v)/20 

Ben davranışı sizi şaşırtabilir sizi uyarmam gerek yuvarlama düzgün çalışıyor, ancak IEEE sayılar tam olarak 1.35 temsil edemez

>>> round(20*1.368161685161)/20 
1.3500000000000001 

. Python 2.7 bu konuda daha akıllıdır ve numarayı yazdırırken en basit gösterim olan 1.35'u seçecektir. Gerçek kayıtlı değer 2.7 ve önceki sürümlerde aynıdır.

+2

Numarada str() 'yi kullanırsanız, uzun ondalık uzaklaşmalıdır. (Veya uzunluğu açıkça sınırlamak için% f veya '.format() işlevini kullanın.) –

+2

Python 2.6'da sadece 1.35 değerini girmek 1.3500000000000001 değerini de verir. Python 2.7 ve Python 3.x'deki güncellenmiş algoritma, 1.35 değerini veriyor. –

+0

@Brandon, @Sven: Nitelikli açıklamalar için teşekkür ederiz. Onlar gerçekten cevabımı tamamlamaya yardımcı oluyorlar (üzgünüm, kendime yardım edemedim). S.S .: "Teşekkür ederim" hakiki. –

3

Ben

round(v * 2, 1)/2 

oldukça hızlı olmalı çalışacaktı. Diğer önerilen varyant

round(v * 20)/20 

bile biraz daha hızlı gibi görünüyor:

$ python -mtimeit "round(1.368161685161 * 2, 1)/2" 
1000000 loops, best of 3: 0.291 usec per loop 
$ python -mtimeit "round(1.368161685161 * 20)/20" 
1000000 loops, best of 3: 0.248 usec per loop 
+0

Aşağı seçmene: bu ifade doğrudur. Oysa aşağı çekilmemesinin nedeni, neden hoşlanmamamın altını çiziyor. Kendi iyiliği için biraz zekidir. –

+1

@Marcelo: İlk ifademi daha da doğal ve hiç de akıllı olmadığımı düşündüm, ama insanların benim yaptığım gibi düşünmediği gerçeğine alıştım. –

+1

Ben de bundan suçluyum bazen. Ben (a == 2)^(b == 3)^(c == 4) 'için çektim çünkü bit-bilge operatörler," boole tiplerine uygulanmamalıdır ". Tabii ki, eğer ben (a == 2)! = (B == 3)! = (C == 4) 'yazıyorsam daha da düzgecik bir kopyasını yapıyorum (ve doğru olarak Python'da,' False^False^True' 'False! = False! = True' ile aynı değildir, ancak bunu zaman zaman C++' da yapıyorum. –