Python'da float'ların kolay ve hoş baskısı?


98

Bir şamandıra listem var. Basitçe yaparsam print, şöyle görünür:

[9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

Listede gezinmek için print "%.2f"bir fordöngü gerektirecek olan kullanabilirdim , ancak o zaman daha karmaşık veri yapıları için işe yaramazdı. Gibi bir şey istiyorum (bunu tamamen uyduruyorum)

>>> import print_options
>>> print_options.set_float_precision(2)
>>> print [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
[9.0, 0.05, 0.03, 0.01, 0.06, 0.08]

Yanıtlar:


25

Bu eski bir soru ama potansiyel olarak yararlı bir şey ekleyeceğim:

Örneğinizi ham Python listelerine yazdığınızı biliyorum, ancak numpybunun yerine dizileri kullanmaya karar verirseniz (bu, örneğinizde mükemmel bir şekilde okunaklı olacaktır, çünkü sayı dizileriyle uğraşıyor görünüyorsunuz), bu komut (neredeyse tam olarak) sizde var uydurduğunu söyledin:

import numpy as np
np.set_printoptions(precision=2)

Ya da sizin durumunuzda daha da iyisi, gerçekten kesin sayıların tüm ondalıklarını görmek istiyorsanız, ancak örneğin sondaki sıfırlardan kurtulmak istiyorsanız, biçimlendirme dizesini kullanın %g:

np.set_printoptions(formatter={"float_kind": lambda x: "%g" % x})

Yalnızca bir kez yazdırmak ve genel davranışı değiştirmemek np.array2stringiçin yukarıdaki argümanların aynısını kullanın .


ağır paket kullanmazdım
Vincent Alex

107

Kimse bunu eklemiştir gibi, bunu yapmak için önerilen yol 2.6+ Python ileriye unutulmamalıdır dize biçimlendirme ile formatPython 3+ için hazır hale getirilmesi.

print ["{0:0.2f}".format(i) for i in a]

Yeni dizgi biçimlendirme sözdiziminin kullanımı zor değildir ve yine de oldukça güçlüdür.

Bunun bir pprintşey olabileceğini düşündüm, ama hiçbir şey bulamadım.


1
Bu kullandığımdı ama .replace("'", "")virgüllerden kurtulmak için ekledim . str(["{0:0.2f}".format(i) for i in a]).replace("'", "")
Steinarr Hrafn Höskuldsson

Bu bir dizi listesi oluşturacaktır. Yazdırılan çıktıda her elemanın ''çevresinde bulunur. Örneğin, a=[0.2222, 0.3333]üretecek ['0.22', '0.33'].
jdhao

Tepeyi ve virgülleri kaldırmak için şunu kullanmalısınız' '.join([{0:0.2f}".format(i) for i in a])
Neb

77

Daha kalıcı bir çözüm, alt sınıflara ayırmaktır float:

>>> class prettyfloat(float):
    def __repr__(self):
        return "%0.2f" % self

>>> x
[1.290192, 3.0002, 22.119199999999999, 3.4110999999999998]
>>> x = map(prettyfloat, x)
>>> x
[1.29, 3.00, 22.12, 3.41]
>>> y = x[2]
>>> y
22.12

Alt sınıflandırma ile ilgili sorun, floatbir değişkenin türünü açıkça arayan kodu kırmasıdır. Ama anlayabildiğim kadarıyla tek sorun bu. Ve basit bir x = map(float, x), dönüşümü geri alır prettyfloat.

Trajik bir şekilde, sadece maymun yama yapamazsınız float.__repr__, çünkü floatdeğişmezdir.

Eğer alt sınıfa istemiyorsanız floatfakat bir işlev tanımlama sakıncası, map(f, x)çok daha fazla özlü[f(n) for n in x]


Daha basit bir çözüm olduğunu düşünürdüm, ama cevabınız açıkça en iyisi, çünkü sorumu gerçekten cevaplayacak tek kişi sizsiniz.
static_rtti

4
Düzenlenmiş sorunuzu gerçekten cevaplayan tek kişi o. Yanıtlayanı aşağılamak değil, ancak bir soruyu açıklığa kavuşturup, üzerinde çalıştığımız bilgilere dayanarak yanıtlayanların geri kalanını küçümseyemezsiniz.
Jed Smith

1
İlk sorum, bir for döngüsünün iyi bir çözüm olmadığını düşündüğümden bahsetti (benim için bir liste anlama aynıdır, ancak bunun net olmadığını kabul ediyorum). Bir dahaki sefere daha net olmaya çalışacağım.
static_rtti

2
[x'deki n için f (n)], haritadan (f, x) çok daha fazla pitoniktir.
Robert T. McGibbon

3
Float alt sınıflamasından yana değilim, ancak tür kontrolünün geçerli bir argüman olduğunu düşünmüyorum. Türleri kontrol ederken, isinstanceeşitlik değil kullanılmalıdır type(). Doğru yapıldığında, bir float alt sınıfı yine de bir float olarak sayılacaktır.
zondo

37

Yapabilirsin:

a = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
print ["%0.2f" % i for i in a]

3
Bu, ['9.00', '0.05', '0.03', '0.01', '0.06', '0.08'] yazdırır - genellikle istemediğiniz tırnak işaretleriyle (geçerli bir kayan nokta listesine sahip olmayı tercih ederim basılı)
Emile

23

"% .2f" gibi bir dizeyi de çarpabileceğinizi unutmayın (örnek: "% .2f" * 10).

>>> print "%.2f "*len(yourlist) % tuple(yourlist)
2.00 33.00 4.42 0.31 

3
çok zarif! Hoşuma
Nathan Fellman

2
-1 korkunç hack. Lütfen başka bir şekilde değil, biçimlendirilmiş dizeleri birleştirin
u0b34a0f6ae

1
öyleyse kaizer.se, "" .join'i mi öneriyorsunuz (["%. 2f"% x listenizdeki x için]). Python'da bu tür bir inşaat yapmak zorundayım.
Gregg Lind

evet, ben öneriyorum " ".join("%.2f" % x for x in yourlist)çünkü biçim dizgisini ve enterpolasyon değerlerini ayırmak, çirkin bir Python deyimi kullanmaktan çok daha kötü.
u0b34a0f6ae

Meraktır. Liste başarısız olurken tuple neden çalışıyor? "Tuple" olmadan hata yapar. Neden?
Joonho Park

9

En kolay seçenek, bir yuvarlama rutini kullanmak olmalıdır:

import numpy as np
x=[9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

print('standard:')
print(x)
print("\nhuman readable:")
print(np.around(x,decimals=2))

Bu çıktıyı üretir:

standard:
[9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.0793303]

human readable:
[ 9.    0.05  0.03  0.01  0.06  0.08]

bu harika bir cevap
jjz

8
print "[%s]"%", ".join(map(str,yourlist))

Bu, yazdırıldığında ikili gösterimdeki yuvarlama hatalarını, sabit bir kesinlik kısıtlaması olmadan (biçimlendirme gibi "%.2f") önleyecektir :

[9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.0793303]

7
l = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]

Python 2:

print ', '.join('{:0.2f}'.format(i) for i in l)

Python 3:

print(', '.join('{:0.2f}'.format(i) for i in l))

Çıktı:

9.00, 0.05, 0.03, 0.01, 0.06, 0.08

Bunun neden daha yüksek olmadığını bilmiyorum. Üçüncü taraf kitaplıklara dayanmayan bir çözüm!
Fl.pf.

6

Önemli basamakların sayısını kontrol etmek için ,% g biçim belirleyicisini kullanın.

Emile'nin çözümüne prettylist2f adını verelim. İşte değiştirilmiş olan:

prettylist2g = lambda l : '[%s]' % ', '.join("%.2g" % x for x in l)

Kullanım:

>>> c_e_alpha_eps0 = [299792458., 2.718281828, 0.00729735, 8.8541878e-12]
>>> print(prettylist2f(c_e_alpha_eps0)) # [299792458.00, 2.72, 0.01, 0.00]
>>> print(prettylist2g(c_e_alpha_eps0)) # [3e+08, 2.7, 0.0073, 8.9e-12]

Önemli basamak sayısında esneklik istiyorsanız, bunun yerine f-string biçimlendirmesini kullanın:

prettyflexlist = lambda p, l : '[%s]' % ', '.join(f"{x:.{p}}" for x in l)
print(prettyflexlist(3,c_e_alpha_eps0)) # [3e+08, 2.72, 0.0073, 8.85e-12]

4

Python 3.1'in varsayılan olarak bunları herhangi bir kod değişikliği yapmadan daha güzel yazdıracağına inanıyorum. Ancak Python 3.1 ile çalışmak için güncellenmemiş herhangi bir uzantı kullanırsanız bu işe yaramaz.


1
Python 3.1, bu kayan değerle eşleşen en kısa ondalık gösterimi yazdıracaktır. Örneğin: >>> a, b = float (1.1), float (1.1000000000000001) >>> a 1.1000000000000001 >>> b 1.1000000000000001 >>> print (a, b) 1.1 1.1
Matt Boehm

4

Liste kompozisyonları sizin dostunuzdur.

print ", ".join("%.2f" % f for f in list_o_numbers)

Dene:

>>> nums = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999]
>>> print ", ".join("%.2f" % f for f in nums)
9.00, 0.05, 0.03, 0.01

5
Oluşturucu ifadesi daha da iyi olurdu: "," .join (list_o_numbers içindeki f için "%. 2f"% f)
efotinis

@efotinis Bunları henüz repertuarıma eklemedim, ama haklısın - bu oldukça seksi.
Jed Smith

1
@Jed: Lütfen "Başkaları benim öğelerimi düzenleyebilir mi ?!" SSS bölümünü okuyun: stackoverflow.com/faq . Her düzenleme iyi bir düzenleme değildir, ancak bu gerçek bir gelişmeydi. Belki cevabınızda her iki tekniği de listeleyebilir ve farkla ilgili bir not ekleyebilirsiniz.
Stephan202

3

Pandaları kullanabilirsin.

İşte listeli bir örnek:

In: import pandas as P
In: P.set_option('display.precision',3)
In: L = [3.4534534, 2.1232131, 6.231212, 6.3423423, 9.342342423]
In: P.Series(data=L)
Out: 
0    3.45
1    2.12
2    6.23
3    6.34
4    9.34
dtype: float64

Bir dikt dd'niz varsa ve onun anahtarlarını satırlar halinde istiyorsanız:

In: d
Out: {1: 0.453523, 2: 2.35423234234, 3: 3.423432432, 4: 4.132312312}

In: P.DataFrame(index=d.keys(), data=d.values())
Out:  
    0
1   0.45
2   2.35
3   3.42
4   4.13

Ve bir DataFrame'e dikte vermenin başka bir yolu:

P.DataFrame.from_dict(d, orient='index')

3

Python 3.6'dan itibaren, f dizelerini kullanabilirsiniz:

list_ = [9.0, 0.052999999999999999, 
         0.032575399999999997, 0.010892799999999999, 
         0.055702500000000002, 0.079330300000000006]

print(*[f"{element:.2f}" for element in list_])
#9.00 0.05 0.03 0.01 0.06 0.08

Kodu çok okunaklı tutarken yazdırma parametrelerini kullanabilirsiniz:

print(*[f"{element:.2f}" for element in list_], sep='|', end='<--')
#9.00|0.05|0.03|0.01|0.06|0.08<--

2

İlk olarak, bir koleksiyondaki öğeler repr'lerini yazdırır. __repr__ve hakkında bilgi edinmelisiniz __str__.

Bu, baskı repr (1.1) ve baskı 1.1 arasındaki farktır. Temsiller yerine tüm bu dizeleri birleştirelim:

numbers = [9.0, 0.053, 0.0325754, 0.0108928, 0.0557025, 0.07933]
print "repr:", " ".join(repr(n) for n in numbers)
print "str:", " ".join(str(n) for n in numbers)

NOT: Python 2.7'de, bu örnek için, "repr" satırı ve "str" ​​satırının sonuçları aynıdır.
ToolmakerSteve

2

Bu problemle sadece pprint kullanarak kayan sayıların bir listesini çıktılamaya çalışırken karşılaştım. İç içe geçmiş anlayışlar kötü bir fikir olabilir, ama işte yaptığım şey:

tups = [
        (12.0, 9.75, 23.54),
        (12.5, 2.6, 13.85),
        (14.77, 3.56, 23.23),
        (12.0, 5.5, 23.5)
       ]
pprint([['{0:0.02f}'.format(num) for num in tup] for tup in tups])

İlk başta jeneratör ifadeleri kullandım, ancak pprint az önce jeneratörü yeniden oluşturdu ...


1

Bu sorunu yaşadım, ancak buradaki çözümlerden hiçbiri tam olarak istediğimi yapmadı (yazdırılan çıktının geçerli bir python ifadesi olmasını istiyorum), peki ya şuna ne dersin:

prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)

Kullanım:

>>> ugly = [9.0, 0.052999999999999999, 0.032575399999999997,
            0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
>>> prettylist = lambda l : '[%s]' % ', '.join("%.2f" % f for f in l)
>>> print prettylist(ugly)
[9.00, 0.05, 0.03, 0.01, 0.06, 0.08]

(.Format () 'ın daha standart bir çözüm olduğunu biliyorum, ancak bunu daha okunaklı buluyorum)


0

SilentGhost'un yorumuna katılıyorum, for döngüsü o kadar da kötü değil. İstediğini elde edebilirsin:

l = [9.0, 0.052999999999999999, 0.032575399999999997, 0.010892799999999999, 0.055702500000000002, 0.079330300000000006]
for x in l: print "%0.2f" % (x)

3
Döngüler için çirkin olmasa da, bu kullanım çok da Pythonic değildir.
Jed Smith

-1

Aşağıdaki kod benim için iyi çalışıyor.

list = map (lambda x: float('%0.2f' % x), list)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.