Kayan noktalı sayıları iki ondalık basamağa sınırlama


1691

13,95'ea yuvarlanmak istiyorum .

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

roundFonksiyon beklediğim şekilde çalışmıyor.



6
Hmm ... Para birimini temsil etmeye mi çalışıyorsunuz? Eğer öyleyse, dolar için şamandıra kullanmamalısınız. Muhtemelen pennies için şamandıralar kullanabilirsiniz veya modellemeye çalıştığınız en küçük ortak para birimi ne olursa olsun, ancak en iyi uygulama, HUAGHAGUAH'ın cevabında önerdiği gibi, ondalık bir temsili kullanmaktır.
SingleNegationElimination

63
Şamandıradaki para birimini temsil etmemek önemlidir. Şamandıralar kesin değildir. Ancak kuruş veya yüzde miktarları tamsayıdır. Bu nedenle, tamsayı para birimini temsil etmenin doğru yoludur.
Davoud Taghawi-Nejad

2
@ DavoudTaghawi-Nejad veya daha fazla noktaya ... Ondalık Tip
Temel

17
Buraya muhtemelen çok geç geliyorum, ama sormak istedim, Python geliştiricileri bu sorunu çözdü mü? Çünkü yuvarlak yaptığımda (13.949999999999999, 2), sadece 13.95 alıyorum. Python 2.7.6 ve 3.4'te denedim. İşe yarıyor. 2009'da 2.7 bile olsa emin değilim. Belki bu bir Python 2.5 şeydir?
bad_keypoints

Yanıtlar:


1690

Sen içine çalıştıran eski bir sorun değil tüm sayılar tam olarak temsil edilebilir kayan nokta numaraları ile. Komut satırı, bellekten tam kayan nokta formunu gösterir.

Kayan nokta gösterimi ile, yuvarlatılmış versiyonunuz aynı sayıdır. Bilgisayarlar ikili olduğundan, kayan nokta sayılarını bir tamsayı olarak saklarlar ve daha sonra ikiye bölerler, böylece 13.95, 125650429603636838 / (2 ** 53) ile aynı şekilde temsil edilir.

Çift kesinlikli rakamların 53 bit (16 basamaklı) hassasiyeti vardır ve normal şamandıraların 24 bit (8 basamaklı) hassasiyeti vardır. Python kayan nokta tipi çift hassas kullanır değerlerini saklamak için.

Örneğin,

>>> 125650429603636838/(2**53)
13.949999999999999

>>> 234042163/(2**24)
13.949999988079071

>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999

Yalnızca iki ondalık basamağın peşindeyseniz (örneğin bir para birimi değeri görüntülemek için), daha iyi birkaç seçeneğiniz vardır:

  1. Tamsayılar kullanın ve değerleri dolar değil sent cinsinden saklayın ve ardından dolara dönüştürmek için 100'e bölün.
  2. Veya ondalık gibi sabit bir nokta numarası kullanın .

27
@Christian Saklanan değer ile bu değeri görüntüleme biçiminiz arasında temel bir fark vardır . Çıktıyı biçimlendirmek, gerektiğinde dolgu eklemenize ve virgül ayırıcılar vb
Temel

22
değerinde olduğunu söz "%.2f" % round(a,2)sizin gibi printf değil, aynı zamanda bu tür şeylere sadece koyabilirsinizstr()
andilabs

20
neden insanlar her zaman kayan nokta yuvarlamada para alırlar? bazen daha az hassasiyetle çalışmak istersiniz.
worc

9
@radtek: İkili değerin (tür float), ondalık sayının (bir insan olarak aşina olduğunuz) mevcut en yakın yaklaşımı olduğunu anlamalısınız . 0.245 gibi (sonlu olarak temsil edilebilir) bir ikili değer yoktur. Basitçe mevcut değildir ve matematiksel olarak var olamaz . 0.245'e en yakın ikili değer 0.245'ten biraz daha azdır , bu nedenle doğal olarak yuvarlanır. Benzer şekilde, ikili dosyada 0.225 diye bir şey yoktur, ancak 0.225'e en yakın ikili değer 0.225'ten biraz daha büyüktür , bu yüzden doğal olarak yuvarlanır.
John Y

12
@radtek: Kelimenin tam anlamıyla bir açıklama istediniz. En basit çözüm gerçekten kullanmaktır Decimalve bu cevapta sunulan çözümlerden biriydi. Diğeri miktarlarınızı tamsayıya dönüştürmek ve tamsayı aritmetiği kullanmaktı. Bu yaklaşımların her ikisi de diğer cevaplarda ve yorumlarda da ortaya çıktı.
John Y

586

Yeni biçim özellikleri vardır, Dize Biçimi Belirtimi Mini Dil :

Aynı şeyi yapabilirsiniz:

"{:.2f}".format(13.949999999999999)

Not 1: Yukarıdaki bir dize döndürür. Şamandıra olarak almak için şunlarla sarın float(...):

float("{:.2f}".format(13.949999999999999))

Not 2: ile sarmak float()hiçbir şeyi değiştirmez:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True

17
virgül eklemek için '{0:,.2f}'.format(1333.949999999)hangi baskıları da yapabilirsiniz '1,333.95'.
Stephen Blum

@ OnurYıldırım: evet, ama ile sarabilirsiniz float(); float("{0:.2f}".format(13.9499999))
Jossef Harush

5
@JossefHarush float () ile sarabilirsiniz, ancak hiçbir şey kazanmadınız. Şimdi yine aynı belirsizliğe sahip bir şamandıra var. 13.9499999999999 ve 13.95 aynı şamandıradır.
Ned Batchelder

4
@NedBatchelder: Eşit olduklarını kabul ediyorum, ancak bu şamandırayı iki ondalık nokta ile sınırlandırıyor :)
Jossef Harush

8
Bu arada, Python 3.6'dan beri f-stringleri kullanabiliriz:f"Result is {result:.2f}"
Andrey Semakin

289

Yerleşik round()eserlerin gayet Python 2.7 veya daha sonra.

Misal:

>>> round(14.22222223, 2)
14.22

Check belgelere .


1
Peki bu bir Python 2.7 başarısız olduğunu anlamak mı? Neden böyle bir temel fonksiyon v 2.7'den v 3'e farklı sonuçlar verir?
MikeM

ama round(2.16, 1)vermek 2.2piton sadece sunuyoruz truncatefonk
jiamo

Örneğin, 2.675 değerini iki ondalık basamağa yuvarlamaya çalışırsanız, bu >>> round(2.675, 2) 2.67 docs.python.org/2/tutorial/floatingpoint.html
danger89

4
Python 3 dokümantasyon sayfasından:Note The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
Richard Dally

1.00000 gibi bir sayı yazdırmak için bu yöntemi kullanmaya çalışırsanız, kaç ondalık sayı belirttiğinizden bağımsız olarak yalnızca 1.0 yazdırılacağını unutmayın.
Josh Correia

142

En basit yaklaşımın format()işlevi kullanmak olduğunu hissediyorum .

Örneğin:

a = 13.949999999999999
format(a, '.2f')

13.95

Bu, iki ondalık basamağa yuvarlanmış bir dize olarak bir kayan sayı oluşturur.


97

kullanım

print"{:.2f}".format(a)

onun yerine

print"{0:.2f}".format(a)

Çünkü ikincisi birden çok değişken çıkarmaya çalışırken çıkış hatalarına yol açabilir (bkz. Yorumlar).


2
Bu saçmalık. Verilen iki ifade Python 2.7 üzerinde aynıdır ve sadece ikinci ifade Python 2.6 için geçerlidir. (Her iki ifade de Python 3 veya Python <2.6 için geçerli değildir.) İlk formun kısalık dışında bir avantajı yoktur.
Mark Dickinson

1
Yani, "{0: .2f} {0: .2f}". Biçimini (a, b) çıktıda hataya yol açar - iki kez 'a' değeri verir. "{:. 2f} {: .2f}". Çıktısını alırken (a, b) 'a' ve 'b' değerlerini verir.
Alexey Antonenko

2
Python 3 için, parantez baskısı (...) eklemeniz yeterlidir. Ve onların içinde yazdığım tek şey doğru.
Alexey Antonenko

"Yani," {0: .2f} {0: .2f} "yazdırın. Biçim (a, b) çıktıda hataya yol açacaktır". Ah. Bu oldukça farklı bir ifade! Belki cevabınızı düzenlemelisiniz? (Şu anki cevapta "yükseltme hatası" ne anlama geliyor? İkinci ifadenin bir istisna yarattığı ancak birincisinin değil olduğu bir duruma örnek verebilir misiniz?)
Mark Dickinson

3
İki değişkeniniz varsa baskıdan sonra ("{0: .2f} {1: .2f}". Formatı (a, b))
Hovo

95

Çoğu sayı şamandıralarda tam olarak temsil edilemez. Eğer sayıyı yuvarlamak istiyorsanız, matematiksel formülünüzün veya algoritmanızın gerektirdiği şeyse, o zaman raund kullanmak istiyorsunuz. Ekranı belirli bir hassasiyetle kısıtlamak istiyorsanız, yuvarlak bile kullanmayın ve sadece bu dize olarak biçimlendirmeyin. (Alternatif bir yuvarlama yöntemiyle görüntülemek istiyorsanız ve ton varsa, iki yaklaşımı karıştırmanız gerekir.)

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

Ve son olarak, belki de en önemlisi, tam matematik istiyorsanız o zaman hiç yüzer istemezsiniz. Genel örnek parayla uğraşmak ve 'sent'leri bir tamsayı olarak saklamaktır.


68

Aşağıdaki kodu deneyin:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99

Ancak dikkatli olun, a'nın değeri hala kesin olmayan bir şamandıradır. Buraya bir göz atın - repl.it/LJs (Sağ bölümün üst kısmındaki "Oturumu Çalıştır" ı tıklayın).
cankurtaran

3
Bu yaklaşıma sahipseniz, daha doğru bir gösterim için 0,5 eklemeniz gerekir. int (a * 100 + 0.5) / 100.0; Math.ceil kullanmak başka bir seçenektir.
arhuaco

3
@ShashankSawant: Bir kere, sunulan cevap yuvarlak değil, kesiliyor. Sonunda yarım ekleme önerisi yuvarlanır, ancak daha sonra sadece roundişlevi kullanarak bunu yapmanın bir yararı yoktur . Başka bir şey için, bu çözüm hala kayan nokta kullandığından, OP'nin orijinal sorunu, bu "çözümün" "düzeltilmiş" sürümü için bile kalır.
John Y

3
-1, bu sadece roundişlevin gereksiz bir şekilde yeniden uygulanmasıdır (bu soruda kullanılmıştır).
interjay

4
@interjay round(), OP'nin belirttiği gibi çalışmazsa gereklidir .
Pithikos

57

TLDR;)

Girdi / çıktının yuvarlama problemi Python 2.7.0 ve 3.1 tarafından kesin olarak çözülmüştür .

Doğru yuvarlanmış bir sayı geri dönüşümlü olarak ileri geri dönüştürülebilir:
str -> float() -> repr() -> float() ...veya Decimal -> float -> str -> Decimal
artık depolama için A Ondalık türü gerekli değildir.


(Doğal olarak, biriken son bit hatalarını ortadan kaldırmak için yuvarlak sayıların toplanması veya çıkarılmasının bir sonucunu yuvarlamak gerekebilir. Açık bir Ondalık aritmetik yine de kullanışlı olabilir, ancak dizeye bir dönüştürme str()(12 geçerli basamağa yuvarlama ile) ) genellikle aşırı doğruluk veya aşırı sayıda ardışık aritmetik işlem gerekmiyorsa yeterince iyidir.)

Sonsuz test :

import random
from decimal import Decimal
for x in iter(random.random, None):           # Verify FOREVER that rounding is fixed :-)
    assert float(repr(x)) == x                # Reversible repr() conversion.
    assert float(Decimal(repr(x))) == x
    assert len(repr(round(x, 10))) <= 12      # Smart decimal places in repr() after round.
    if x >= 0.1:                              # Implicit rounding to 12 significant digits
        assert str(x) == repr(round(x, 12))   # by str() is good enough for small errors.
        y = 1000 * x                             # Decimal type is excessive for shopping
        assert str(y) == repr(round(y, 12 - 3))  # in a supermaket with Python 2.7+ :-)

belgeleme

Sürüm notlarına bakın Python 2.7 - Diğer Dil Dördüncü paragrafı değiştirir:

Kayan nokta sayıları ve dizeler arasındaki dönüşümler artık çoğu platformda doğru şekilde yuvarlanmaktadır . Bu dönüşümler birçok farklı yerde gerçekleşir: şamandıralar ve karmaşık sayılar üzerinde str (); şamandıra ve kompleks yapıcılar; sayısal biçimlendirme; seri ve kullanma yüzen ve karmaşık sayıları de-serializing marshal, pickleve jsonmodüller; Python kodunda şamandıra ve sanal değişmez değerlerin ayrıştırılması; ve Ondalık-kayan nokta dönüştürme.

Bununla ilgili olarak, kayan nokta sayısı x'in repr () değeri artık doğru yuvarlama altında (yuvarlamadan ikiye yuvarlama modunda) x'e geri dönmesi garanti edilen en kısa ondalık dizeye dayalı bir sonuç döndürür . Daha önce, x ila 17 ondalık basamağa yuvarlamaya dayalı bir dize veriyordu.

İlgili konu


Daha fazla bilgi:float Python 2.7'den önceki biçimlendirmesi akıma benzerdi numpy.float64. Her iki tip de 52 bit mantis ile aynı 64 bit IEEE 754 çift ​​kesinlik kullanır. Büyük bir fark, np.float64.__repr__aşırı bir ondalık sayı ile sık sık biçimlendirilmesidir, böylece bit kaybedilemez, ancak 13.94999999999999999 ile 13.950000000000001 arasında geçerli bir IEEE 754 numarası yoktur. Sonuç hoş değil ve dönüşüm repr(float(number_as_string))numpy ile tersine çevrilemez. Diğer yandan:float.__repr__her basamak önemli olacak şekilde biçimlendirilir; sekans boşluksuzdur ve dönüşüm tersine çevrilebilir. Basitçe: Belki bir numpy.float64 numaranız varsa, sayısal işlemciler için değil, insanlar için biçimlendirmek için normal şamandıraya dönüştürün, aksi takdirde Python 2.7+ ile başka bir şey gerekmez.


Neden reddedildi? Soru, Python float(çift kesinlik) ve normal round, numpy.double ve dizeye dönüşümü hakkında değildi. Düz Python yuvarlama gerçekten Python 2.7'den daha iyi yapılamaz. Cevapların çoğu 2.7'den önce yazılmıştır, ancak orijinal olarak çok iyi olmalarına rağmen eskimişlerdir. Cevabımın nedeni bu.
hynekcer

"Gizli bit" i eklediğinizde 1, "kademeli alt akış" hariç , dolaylı olarak 53 bit .
Rick James

Bu yuvarlak bir hata değil, ekran hatası.
Rick James

Evet, çok iyi biliniyor. Ancak Python 2.7 Sürüm notlarında veya metnimde ya da hiçbir şeyde bir şeye itiraz ederseniz bir bağlamı özlüyorum. Bu sorunun amacı gereğinden daha karmaşıktır. Ayrıca , belirli 32 bit Intel yongalarındaki yuvarlama hatası nedeniyle dizeden float'a dönüşümün Python 2.7'de düzeltildiği ve "round () işlevinin de artık doğru şekilde yuvarlandığı" eklenmelidir. ( Sürüm notları - 3.1 özellikleri 2.7'ye desteklenir ). Kabul edebilir misin?
hynekcer

1
Maalesef bu oldu a*bvs b*a. Linkler için teşekkürler - Nostalji.
Rick James

52

Python <3 (ör. 2.6 veya 2.7) ile bunu yapmanın iki yolu vardır.

# Option one 
older_method_string = "%.9f" % numvar

# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)

Ancak 3'ün üzerindeki Python sürümleri için (örn. 3.2 veya 3.3), ikinci seçeneğin tercih edildiğine dikkat edin .

İkinci seçenek hakkında daha fazla bilgi için , Python belgelerinden dize biçimlendirme ile ilgili bu bağlantıyı öneriyorum .

Birinci seçenek hakkında daha fazla bilgi için, bu bağlantı yeterli olacak ve çeşitli bayraklar hakkında bilgi sahibi olacaktır .

Başvuru: Kayan nokta numarasını belirli bir kesinlike dönüştürün ve sonra dizeye kopyalayın


Bir tamsayıyı nasıl temsil edersiniz? "{İ3}". Biçimini (numvar) kullanırsam bir hata alıyorum.
skytux

Demek istediğim bu: Eğer numvar=12.456, o zaman "{:.2f}".format(numvar)verir 12.46ama "{:2i}".format(numvar)bir hata verir ve ben bekliyorum 12.
skytux

50

Çıktı biçimini değiştirebilirsiniz:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95

47

Burada kimse henüz bahsetmemiş gibi görünüyor, bu yüzden güzelce düzgün olduğunu düşünüyorum Python 3.6'nın f-string / template-string biçiminde bir örnek vereyim:

>>> f'{a:.2f}'

Operatörlerle ve parenlere ihtiyaç duymadan daha uzun örneklerle de iyi çalışır:

>>> print(f'Completed in {time.time() - start:.2f}s')

39

Python'da değeri 2 ondalık basamağa yuvarlamak için format operatörünü kullanabilirsiniz :

print(format(14.4499923, '.2f')) // output is 14.45

4
Bu dize döndürür
Jemshit Iskenderov

29

Python 2.7'de:

a = 13.949999999999999
output = float("%0.2f"%a)
print output

1
Bu hiç yardımcı olmuyor. outputile tam olarak aynı değere sahiptir a, bu nedenle son satır print ayerine yazmış da olabilirsiniz print output.
Mark Dickinson

@MarkDickinson Lütfen tekrar deneyebilir misiniz? Çünkü derleyicimde beklendiği gibi çalışıyor.
Shashank Singh

1
Demek istediğim eksik. Evet, kodunuz yazdırılıyor 13.95. Ancak , Python 2.7'deki print abu özel değer için a, biçimlendirme adımının amacının ne olduğu gerçekten net değil.
Mark Dickinson

@ MarkDickinson Kodu düzenledim. 'Print a' öğesinin "print output" ile aynı değeri yazdırdığını kabul ediyorum. Ancak "a == output" ile karşılaştırırsanız, biçimlendirme adımı "a" değişken değerini iki ondalık basamağa yuvarladığı için sonuç "False" olur.
Shashank Singh

1
Gösterdiğiniz a == outputkodu gerçekten denediniz mi? Benim için veriyor Trueve sizin için de olduğundan şüpheleniyorum.
Mark Dickinson

22

Python dersinde Kayan Nokta Aritmetiği adlı bir ek bulunmaktadır : Sorunlar ve Sınırlamalar . Oku onu. Neler olduğunu ve Python'un neden elinden gelenin en iyisini yaptığını açıklıyor. Sizinkiyle eşleşen bir örneği bile var. Biraz alıntı yapmama izin verin:

>>> 0.1
0.10000000000000001

round() beklediğiniz tek basamağa geri kesmek için bu işlevi kullanabilirsiniz . Ancak bu bir fark yaratmaz:

>>> round(0.1, 1)
0.10000000000000001

Sorun şu ki, depolanan ikili kayan nokta değeri “0.1” zaten mümkün olan en iyi ikili yaklaşımdı 1/10, bu yüzden tekrar yuvarlamaya çalışmak daha iyi olamaz: zaten olduğu kadar iyi.

Başka bir sonuç, 0.1 tam olarak olmadığı için 1/10, on değerin toplanmasının 0.1tam olarak verilemeyebileceğidir 1.0:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

Bir alternatif ve sorunlarınıza çözüm decimalmodülü kullanmak olacaktır .


18

@Matt'ın belirttiği gibi, Python 3.6 f-dizeleri sağlar ve ayrıca iç içe parametreleri de kullanabilirler :

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

hangisi görüntülenecek result: 2.35



11

Ondalık nesne ve round () yönteminin birleşimini kullanın.

Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1 
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')

7

Kayan noktayı Python ve JavaScript gibi tip-dinamik dillerde düzeltmek için bu tekniği kullanıyorum

# For example:
a = 70000
b = 0.14
c = a * b

print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980

Ondalık'ı aşağıdaki gibi de kullanabilirsiniz:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')

getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')

1
getcontext().prec = 6sadece işlevin kapsamı veya tüm yerler için çalışır?
Julio Marins

1
Bağlamlar aritmetik işlemler için kullanılan ortamlardır. Hassasiyeti yönetir, yuvarlama için kurallar belirler, hangi sinyallerin istisna olarak değerlendirileceğini belirler ve üsler için aralığı sınırlar. Her iş parçacığının kendi geçerli bağlamı vardır @JulioMarins
Siamand

7
from decimal import Decimal


def round_float(v, ndigits=2, rt_str=False):
    d = Decimal(v)
    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
    if rt_str:
        return v_str
    return Decimal(v_str)

Sonuçlar:

Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'

6
orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float)) 

14.54


5

Peki bu gibi bir lambda işlevi hakkında:

arred = lambda x,n : x*(10**n)//1/(10**n)

Bu şekilde şunları yapabilirsiniz:

arred(3.141591657,2)

ve Al

3.14

4

1,2,3 gibi basit:

  1. Kullanım ondalıkhızlı doğru yuvarlanmış ondalık kayan nokta aritmetiği için modülü :

    d = Ondalık (10000000.0000009)

yuvarlama elde etmek için:

   d.quantize(Decimal('0.01'))

ile sonuçlanacak Decimal('10000000.00')

  1. KURU yukarıda yapmak:
    def round_decimal(number, exponent='0.01'):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(exponent))

VEYA

    def round_decimal(number, decimal_places=2):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(10) ** -decimal_places)
  1. bu yanıtı oyla :)

PS: başkalarının eleştirisi: biçimlendirme yuvarlama değildir.


2

Bir sayıyı bir çözünürlüğe yuvarlamak için en iyi yol, herhangi bir çözünürlükle (iki ondalık veya 0,01 adım için 0,01) çalışabilen şu değerdir:

>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95

>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0

3.4.3 ve numpy 1.9.1'de benim için çalışmıyor mu? >>> nump'yi np olarak içe aktar >>> res = 0.01 >>> değer = 0.184 >>> np.round (değer / res) * res 0.17999999999999999
szeitlin

1
Belgeleri ararken sorunun numpy.rounddoğruluk / kesinlikten geldiğini görüyorum . Bu yüzden çözünürlükle çarpmadan önce int olarak tanımlanması gerekir. Kodu güncelledim. Bunun için teşekkür ederim!
iblasi

Gerekli olan tek şey numpy.float64np.round'un sonucunu floatveya sadece kullanmak için dönüştürmektir round(value, 2). 13.949999999999999 (= 1395 / 100.) ile 3.950000000000001 (= 1395 * .01) arasında geçerli bir IEEE 754 numarası yok. Neden yönteminizin en iyisi olduğunu düşünüyorsunuz? Orijinal değer 13.949999999999999289 (= değer = yuvarlak (değer, 2)) 13.95000000000000178 (np.float96 ile basılmıştır) değerinden daha kesindir. Numpy için de diğer bilgiler artık eklenir cevabım muhtemelen yanlışlıkla downvoted söyledi. Başlangıçta numpy ile ilgili değildi.
hynekcer

@hynekcer Cevabımın en iyisi olduğunu düşünmüyorum. Sadece n ondalık sayı için limit float örneği tanımlamak istedim ancak tanımlanan çözünürlüğe en yakın olanı Söylediğin gibi kontrol ettim, senin yerine @szeitlin örneği için intde kullanabilirsin float. Ek yorumunuz için teşekkür ederiz. (Üzgünüm ama seni küçümsemedim)
iblasi

Sayısal işleme (pandalar) için tamamen yeni bir bağımlılık eklemek "en iyi yol" mu?
Hejazzman

1

lambda x, n: int (x * 10 n + .5) / 10 n uzun yıllar boyunca birçok dilde benim için çalıştı .


-13

Kullandığım yöntem dize dilimleme yöntemidir. Nispeten hızlı ve basit.

İlk olarak, şamandırayı bir dizeye dönüştürün, olmasını istediğiniz uzunluğu seçin.

float = str(float)[:5]

Yukarıdaki tek satırda, değeri bir dizeye dönüştürdük, sonra dizeyi yalnızca ilk dört basamağına veya karakterine (dahil) tuttuk.

Umarım yardımcı olur!


2
Lütfen birden fazla soruya özdeş cevaplar göndermeyin.
vaultah

18
WOW ... tdh ... Asla herhangi bir muhasebe yazılımı yapmayın ... Sayı 113.94 olursa ne olur? Bu 113.9 ... 0.04 eksik bırakarak sonuçlandı .... Ayrıca bu zaten 5 yıl önce cevap var ....
Kızgın 84
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.