2016-11-16 21 views
9

Python 3'teki bir ondalık sayıyı yarıya indirmeye ayarlandığında neden Python 3'ün ondalık bir düzlemi yuvarladığını açıklayan herhangi bir kişi açıklayabilir veya önerebilir. doğru 3'e:Python 3 ROUND_HALF_UP bağlamıyla ondalık yuvarlama yarısı

Python 3.4.3 ve 3.5.2:

>>> import decimal 
>>> context = decimal.getcontext() 
>>> context.rounding = decimal.ROUND_HALF_UP 
>>> round(decimal.Decimal('2.5')) 
2 
>>> decimal.Decimal('2.5').__round__() 
2 
>>> decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP) 
Decimal('3') 

Python 2.7.6: Görüşme sırasında round bir şamandıra değer elde etmesini

>>> import decimal 
>>> context = decimal.getcontext() 
>>> context.rounding = decimal.ROUND_HALF_UP 
>>> round(decimal.Decimal('2.5')) 
3.0 
>>> decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP) 
Decimal('3') 

cevap

9

Bildirimi Sonuç olarak, Decimal değil. round değeri bir float'a zorlamak ve sonra bir floatın yuvarlanması kurallarına göre yuvarlamaktır.

round() numaralı telefonu aradığınızda isteğe bağlı ndigits parametresini kullanırsanız, Ondalık bir sonucu alırsınız ve bu durumda beklediğiniz şekilde işlenecektir. o round(someDecimal) bir int döndüren ancak round(someDecimal, ndigits) bir ondalık döndürür, ancak Python 3.3 olur ve daha sonra neler olacağı kuvvetle muhtemel belgelenmiştir nerede bulamadım

Python 3.4.1 (default, Sep 24 2015, 20:41:10) 
[GCC 4.9.2 20150212 (Red Hat 4.9.2-6)] on linux 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import decimal 
>>> context = decimal.getcontext() 
>>> context.rounding = decimal.ROUND_HALF_UP 
>>> round(decimal.Decimal('2.5'), 0) 
Decimal('3') 

. Python 2.7'de, round()'u aradığınızda her zaman bir geri kalanı alırsınız ancak Python 3.3, Decimal'un Python yerleşikleriyle entegrasyonunu geliştirmiştir.

olarak Decimal.__round__() için, bir yorum round() delegelerini kaydetti ve bu gerçekten aynı davranışı gösterir:

>>> Decimal('2.5').__round__() 
2 
>>> Decimal('2.5').__round__(0) 
Decimal('3') 

Ben Fraction belgeleri diyor unutmayın:

__round__() 
__round__(ndigits) 
The first version returns the nearest int to self, rounding half to even. 
The second version rounds self to the nearest multiple of Fraction(1, 10**ndigits) 
(logically, if ndigits is negative), again rounding half toward even. 
This method can also be accessed through the round() function. 

Böylece davranış tutarlıdır hiçbir argüman olmadan, sonucun türünü değiştirir ve yarısına bile yuvarlar, ancak Decimal'un __round__ yönteminin davranışını belgelemediği görülür. .

Açıklamada Barry Hurley'in yorumlarda belirtildiği gibi düzenleyin, round(), isteğe bağlı argümanlar ve isteğe bağlı argüman verilirse "kayan nokta değeri" olmadan çağrılırsa int döndürüyor. Duncan'ın cevap @ üzerinde Genişleyen https://docs.python.org/3/library/functions.html#round

+0

Teşekkürler @Duncan için açıklama, bu şeyleri anlamak için her zaman iyidir. Ndigits belirtip belirtmediğinize bağlı olarak farklı bir _type_ dosyasının döndürülmesi çok garip görünüyor. –

+1

Eklenti olarak, python 3 docs 'number .__ round __ (ndigits) 'delege ettiğini ve' decimal 'modülünün kendi' __round__' yöntemi olan –

+1

@ Dunca'ya sahip olduğunu belirtir; float olsa: "Eğer ndigits atlanırsa veya None ise, girdiye en yakın tam sayıyı döndürür." https://docs.python.org/3/library/functions.html#round –

2

, round yerleşik fonksiyonu (istatistikte norm olan) en yakın çift sayıya tura piton 2 ve piton 3 arasında değişti.

Python2 dokümanlar: İki katları eşit yakın ise

..., yuvarlama yani, örneğin, yuvarlak (0.5) 1.0 ve yuvarlak (-0.5) olduğu uzaklıkta 0 (yapıldığında - 1.0).

Python3 docs: İki katları aynı derecede yakınsa

..., yuvarlama bile yüzden, örneğin, hem yuvarlak seçim ((0.5) ve yuvarlak doğru yapılır

(-0,5) 0 ve yuvarlak (1.Hiçbir argüman Duncan'ın cevap @ için ndigits (kredi verilmesi halinde 5) 2) round yana

round o float s için olduğu gibi aynı şekilde davranır,) float dönüşür. (Python3 olarak)

Örnekler: Bu 3'e karşı Python 2 round yuvarlanmasıyla modu ve C için Python'dan Decimal yeniden uygulama arasında değişiklik bir kombinasyonudur

>>> round(2.5) 
2 
>>> round(2.500000001) 
3 
>>> round(3.5) 
4 
+0

Teşekkürler @Billy, ama her iki turda (1.5) ve yuvarlak (2.5) Python 3'te 2 verir, ki bu 1.5 ve 2.5 yüzerlerin içsel olarak nasıl temsil edildiğini tahmin ediyorum. Python 2'deki yuvarlaklar, bunlar için, python 3'e karşılık, bu değerlere göre yüzer. –

+2

İç gösterimleri ile ilgisi yoktur. Python'un kayan nokta uygulaması, 1.5 ve 2.5 * kesin olarak * gösterebilir (yani, 1.1 sayısıyla alacağınız gibi kayan nokta yuvarlama hataları yok). 1.5 tam * eşittir * 1 ve 2 mesafeden eşittir, python 3 en yakın çift sayıya döner, bu da 2'dir. Benzer şekilde, 2.5 * tam olarak * 2 ve 3 arasındadır, yani en yakın çift sayıya yuvarlanır. yine 2. – Billy

1

("Diğer bakınız son büyük ölçekli değişiklikler "Features for 3.3 section PEP 398").

round için, yuvarlama stratejisi What's New In Python 3.0 de görülebileceği gibi [da Python 3.x rounding behavior bakınız] değiştirildi. Ayrıca, round Python nesne için tanımlanan find an appropriate __round__ yöntemine 3 ilk çalışır geçti:

>>> round('1') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: type str doesn't define __round__ method 

iken Python 2.x ilk çalışır coerce it specifically to a float ve daha sonra o yuvarlak:

>>> round('1') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: a float is required 

Decimal için, Python

>>> Decimal.__round__ 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: type object 'Decimal' has no attribute '__round__' 
: 2, uygulama bile çağrılacak bir __round__ yöntemi yoksun

Decimal nesnesindeki round nesnesini çağırmak, rounded using _Py_double_round numaralı float numarasına zorladı; Bu, ndigits için bir değer sağlanmışsa, hiçbir zaman geri dönüşsüz olarak float ile sonuçlandı. decimal, 2.x için Python'da uygulanır ve 3.2'a kadar Python 3 için?

o C yeniden hayata geçirildi olarak

In Python 3.3 it got shinny new __round__ method: round(<Decimal_object>) çağrıldığında

>>> Decimal.__round__ 
<method '__round__' of 'decimal.Decimal' objects> 

ve şimdi, round tarafından kurtarılır.

Bu, eğer varsa, bunun üzerine quantize çağırır ve yeni yuvarlak Decimal nesnesi geri döndürür varsayılan içerik (ROUND_HALF_EVEN) bağımsız değişken ndigits birlikte değilse kullanılarak hemen returns a PyLong (bir tamsayı), C içinde PyDec_Round eşlenir ve.