Python'un math.ceil () ve math.floor () işlemleri neden tamsayı yerine float döndürüyor?


171

Birisi bunu açıklayabilir mi (doğrudan dokümanlardan - benimkini vurgulayın):

math.ceil (x) x'in tavanını bir float olarak döndürür , en küçük tamsayı değeri x'den büyük veya ona eşittir.

math.floor (x) x'in tabanını bir kayan nokta olarak , x'den küçük veya ona eşit en büyük tamsayı değeri olarak döndürür .

Neden tanımları tamsayı hesaplaması gerektiğinde yüzen .ceilve .floordönüş yüzer?


DÜZENLE:

Eh bu da neden olarak bazı çok iyi argümanlar var olmalıdır yüzen dönün ve ne zaman ben sadece fikre alışmak oldu @jcollado onlar aslında dikkat çekti do Python 3'te dönüş int'leri ...


1
Benim tahminim x'in bir tamsayı değil bir şamandıra olması olabilir, ancak Python'u bilmediğim veya kullanmadığımdan, bir başkasının daha kesin olarak cevap vermesine izin vereceğim. :)
Adam V

6
@ Adam- ama tavan / zemin operasyonlarının bütün amacı şamandıraları tam sayılara yuvarlamak!
Yarin

1
Bu da ilk karşılaştığımda beni rahatsız etti, çünkü yanlış görünüyor. En azından kullanmak çok zor değil int(floor(n)).
wim

1
İronik olarak (taşmaları önlemek için şamandıralar kullanıldıkça), zeminin temsili nedeniyle, 64 bitlik bir int taşmasından çok önce, taban / tavan tarafından döndürülen değer, düşük basamaklarda anlamsızdır. [32 bitlik eski günlerde bu doğru değildi.]
Yves Daoust

Yanıtlar:


100

Kayan nokta sayı aralığı genellikle tamsayı aralığını aşıyor. Kayan nokta değerini döndürerek, işlevler, temsil edilebilir tamsayı aralığının dışında kalan giriş değerleri için makul bir değer döndürebilir.

floor()Şunu düşünün: Bir tamsayı döndürülürse ne floor(1.0e30)döndürülmelidir?

Şimdi, Python'un tam sayıları artık keyfi bir hassasiyet olsa da, her zaman böyle değildi. Standart kütüphane fonksiyonları, eşdeğer C kütüphanesi fonksiyonlarının etrafındaki ince sargılardır.


13
Ve Python tam sayıları artık keyfi bir hassasiyet olsa da, zemini ve tavanı tamsayılarla temsil edilemeyen şamandıralar hala var. floor(float("inf"))Veya deneyin ceil(float("nan")).
Michael Hoffman

4
@ Michael- Görünüşe göre P3'te bunu denerseniz OverflowExceptions alacaksınız. Bkz jcollado cevabını
Yarin

4
Ee, 'uzun' tip ('bigint' olarak da bilinir) döndürmeli, değil mi? Bana açık bir cevap gibi görünüyor, ama şimdi bir şekilde saf olduğumu hissediyorum.
koschei

3
@koschei: Python 3.x'te var, jcollado'nun cevabına bakınız.
Greg Hewgill

Ayrıca , menzil içindeki sayılar için bile bunun mantıklı olduğu başka bir yanıtın yorumuna bakın .
ivan_pozdeev

97

Diğer cevapların da işaret ettiği gibi, python'da muhtemelen taşma problemlerini önlemek için tarihsel nedenlerden dolayı yüzüyorlar. Ancak, python 3'te tamsayılar döndürürler.

>>> import math
>>> type(math.floor(3.1))
<class 'int'>
>>> type(math.ceil(3.1))
<class 'int'>

Daha fazla bilgiyi PEP 3141'de bulabilirsiniz .


@ jcollado- P3'te tamsayı döndürdüklerini nereden görüyorsunuz?
Yarin

4
@Yarin Yukarıdaki komutları yeni yazdım. Ayrıca float("inf")veya ile denerseniz float("nan")bir OverflowErroristisna alırsınız .
jcollado

10
Bütünlüğü sağlamak için, Python'un numpy.floorve ceildönüş yüzer (<class 'numpy.float64'>)
Neil G

1
@jcollado: float("inf")Python 2.7 veya 3 bir istisna üretmez
Endolit

1
@ endolith Haklısın, bunu kontrol ettim ve artık gerçekleşmiyor. Muhtemelen bu Aralık 2011'den beri değiştirilen bir şey.
jcollado

18

Karışıklığınızın kaynağı yorumunuzda belirgindir:

Tavan / zemin operasyonlarının asıl amacı şamandıraları tamsayıya dönüştürmektir!

Tavan ve zemin operasyonlarının noktası kayan nokta verilerini integral değerlere yuvarlamaktır . Bir tür dönüştürme yapmamak. Tamsayı değerlerini alması gereken kullanıcılar işlemi takiben açık bir dönüşüm yapabilir.

Eğer elinizde mevcut olan tek şey bir tamsayı döndüren bir tavan veya şamandıra işlemi olsaydı, önemsiz bir şekilde yuvarlatılmış bir değere bir yuvarlak uygulamak mümkün olmayacaktır. Öncelikle girişin temsil edilebilir tamsayı aralığında olduğunu kontrol etmeniz, ardından işlevi çağırmanız gerekir; NaN ve sonsuzlukları ayrı bir kod yolunda işlemeniz gerekir.

Ayrıca, IEEE 754 ile uyumlu olmak istiyorsanız, kayan noktalı sayıları döndüren tavan ve zemin versiyonlarına sahip olmalısınız .


Stephen- Yorumumu yeniden yazdım - Dönüştürmek değil yuvarlak demek istedim. Ama bu karışıklığımın kaynağı değildi - daha ziyade menzil eşitsizliğini tanımıyordum.
Yarin

Ne yazık ki, bugün oylarım bitti. Bu doğru cevaptır, temsili sınırlamalarından çok daha fazlasıdır.
Marcin

13
Programlama yıllarımda, istediğim bir durumla karşılaştığımı hatırlamıyorum zeminin / tavanın sonucunun tamsayı yerine şamandıra olmasını . Python3 gerçeği yapar bu aslında yapmak daha faydalı bir şey olduğunu dönüş tamsayılar gösterileri. "Nokta ..." iddiasını almıyorum; noktayı bir programcının isteyebileceğinden ziyade ne yaptığına bağlı olarak tanımladığınız anlaşılıyor.
ShreevatsaR

2
@ShreevatsaR Bu durumu birkaç kez yaşadım (ancak esas olarak bir Python bağlamının dışında). Hatırladığım zamanlar Mandelbrot setleri ile çalışırken. Bazen integral bir değer yapmanız gerekir, ancak hemen sonra değere bir miktar kayan nokta işlemi uygulayın (örneğin, 0,5 ölçekleme). Daha sonra, döşenmiş şamandırayı tutmak ve ona bir kayan nokta işlemi uygulamak önce bir int'e dönüştürüldükten sonra hemen tekrar şamandıra dönüştürmekten çok daha etkilidir.
blubberdiblub

17

Çünkü python'un matematik kütüphanesi, C matematik kütüphanesinin etrafında yüzer dönen ince bir sarıcıdır.


C matematik kütüphanesi keyfi tamsayıları destekliyor mu? Çünkü diğer piton matematik fonksiyonlarının dönüşü budur.
endolit

5

Python 2.4'ten önce, bir tam sayı kesilmiş gerçek sayıların tamamını tutamadı.

http://docs.python.org/whatsnew/2.4.html#pep-237-unifying-long-integers-and-integers


2
Şimdi de "tam kesilmiş gerçek sayılar dizisini" tutamaz, çünkü bu sınırsız bir settir ve bu nedenle sonsuz miktarda hafıza gerektirir. Küçük bir sub alt kümesi olan kesilmiş şamandıra aralığını tutabilir.
leftaroundabout

6
@seftaroundabout - seçici seçici! Ne demek istediğimi biliyordun.
Mark Ransom

4

Şamandıra aralığı tamsayılardan daha büyük olduğundan - bir tamsayı döndürmek taşabilir


7
Tamsayılar Python'da taşmıyor; tamsayıları çok büyüdüklerinde bigint'e dönüşür. Bir Python yorumlayıcısı açın ve "2 ** 500" yazın, böylece int gibi her şekilde işlem yapabileceğiniz bir nesne elde edersiniz.
koschei

@koschei: Sonsuzluğu temsil etmeye çalışırken bigints bile taşar.
Stephen Canon

4

Bu çok ilginç bir soru! Bir şamandıra, üssü (= bits_for_exponent) saklamak için bazı bitler gerektirdiğinden 2**(float_size - bits_for_exponent), her zamankinden daha büyük herhangi bir kayan nokta sayısı ! Diğer uçta, negatif üslü bir şamandıra 1, 0veya 'dan birini verecektir -1. Bu, tamsayı aralığı ile kayan aralık aralığının tartışılmasını sağlar, çünkü bu işlevler sayı tam sayı türünün aralığının dışında olduğunda orijinal sayıyı döndürür. Python fonksiyonları işlevin sarmalayıcılarıdır Cve bu gerçekten Cbir tamsayı döndürmeleri ve tavan / zemini aramadan önce programlayıcıyı menzil / NaN/ Infkontrol yapmaya zorlamaları gereken fonksiyonların bir eksikliğidir .

Dolayısıyla, mantıksal cevap, bu fonksiyonların tamsayı aralığında bir değer döndürecekleri tek zaman ve böylece bir şamandıra döndürmeleri gerçeği bir hatadır ve bunu gerçekleştirmek için çok akıllısınız!


1

Belki diğer diller de bunu yapıyor, bu yüzden genellikle kabul edilen bir davranıştır. (Diğer yanıtlarda gösterildiği gibi iyi nedenlerden dolayı)


Ya da Charles ne dedi. :)
Almo
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.