Python Infinity - Herhangi bir uyarı var mı?


179

Python'un pozitif ve negatif sonsuzluğu var:

float("inf"), float("-inf")

Bu sadece bazı uyarılar olması gereken özellik türü gibi görünüyor. Dikkat etmem gereken bir şey var mı?


25
Sabitin 1e309, olarak yorumlanacağını +infve -1e309olarak yorumlanacağını unutmayın -inf.
Chris Taylor

Yanıtlar:


97

Basit aritmetik işlemlerden sayı olmayan (NaN) değerleri almaya devam edebilirsiniz inf:

>>> 0 * float("inf")
nan

Normalde normal aritmetik hesaplamalar yoluyla bir değer elde edemeyeceğinizi unutmayın inf:

>>> 2.0**2
4.0
>>> _**2
16.0
>>> _**2
256.0
>>> _**2
65536.0
>>> _**2
4294967296.0
>>> _**2
1.8446744073709552e+19
>>> _**2
3.4028236692093846e+38
>>> _**2
1.157920892373162e+77
>>> _**2
1.3407807929942597e+154
>>> _**2
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
OverflowError: (34, 'Numerical result out of range')

infBir hakkında bilmek daha iyidir, böylece değeri, alışılmadık semantik ile çok özel bir değer olarak kabul edilir OverflowErrorziyade bir olmasındansa hemen bir istisna yoluyla infsessizce hesaplamalar enjekte değeri.


8
Basit bir şamandıra eklenmesi, çarpımı, vb. Mutlu bir şekilde inf üretecektir: f = 1.3407807929942597e + 154; f * f => inf. Bir OverflowError yükseltmek için bir ** istisna gibi görünüyor.
eregon

@eregon, aslında, **biraz arabası gibi görünüyor. Gerçek sayılarla taştığında, bir hata atar, ancak işlenenlerinden herhangi biri infya da olduğunda -inf, ya 0.0da döndürür inf. O yüzden yapar doğru işi girişi Inifinty olduğunda, ancak sonuç sonsuzluk olmalıdır değilken.
Abel

2
@Abel Bu adam değil. Taşma, sayının çok büyük olduğu anlamına gelir. Onu temsil etmek için çok büyük, ama yine de sonsuzdan çok daha küçük. Böyle bir yere sonsuzluk koymak, özel uygulama mantığınızın istisna işleyicisi için yararlı olabilir, ancak genel olarak Python için yanlış olur.
Lutz Prechelt

6
@Lutz çarpma olarak ortaya çıkarsa, hala tutarsız bir davranıştır. Kesinlikle büyük * büyük de sonsuz değildir.
Richard Rast

100

Python'un uygulaması , rehber olarak kullanabileceğiniz IEEE-754 standardını oldukça iyi takip eder , ancak derlendiği temel sisteme dayanır, bu nedenle platform farklılıkları oluşabilir. Son zamanlarda, "sonsuzluğa" ve "inf" e izin veren bir düzeltme uygulanmıştır , ancak bu çok az öneme sahiptir.

Aşağıdaki bölümler, IEEE kayan nokta aritmetiğini doğru bir şekilde uygulayan herhangi bir dil için eşit derecede geçerlidir, sadece Python'a özgü değildir.

Eşitsizlik karşılaştırması

Sonsuzlukla ve operatörlerden büyük >veya küçükten büyüklerle uğraşırken <, aşağıdakiler önemlidir:

  • dahil herhangi bir sayı +infdaha yüksek-inf
  • dahil herhangi bir sayı -infdaha küçüktür+inf
  • +infolduğu ne yüksek ne de düşük daha+inf
  • -inf ne daha yüksek ne de daha düşük -inf
  • içeren herhangi bir karşılaştırma NaNyanlıştır ( infne daha yüksek ne de daha düşüktür NaN)

Eşitlik karşılaştırması

Eşitlik için karşılaştırıldığında, zaman +infve +infeşittir gibidir -infve -inf. Bu çok tartışılan bir konudur ve sizin için tartışmalı gelebilir, ancak IEEE standardındadır ve Python böyle davranır.

Tabii ki, +infeşit değildir -infve NaNkendisi de dahil olmak üzere her şey eşit değildir NaN.

Sonsuzluk ile hesaplamalar

Sonsuzluğa sahip çoğu hesaplama, her iki işlenen de sonsuz değilse, işlem bölümü veya modulo olduğunda veya sıfır ile çarpıldığında, akılda tutulması gereken bazı özel kurallar vardır:

  • sıfır ile çarpıldığında, sonuç tanımlanmamışsa, NaN
  • herhangi bir sayıyı (sonsuzluğun kendisi hariç) sonsuzluk ile bölerek, 0.0veya -0.0²'yi verir .
  • pozitif veya negatif sonsuzluğu pozitif veya negatif sonsuzluğa böldüğünde (modulo dahil) sonuç tanımsızdır NaN.
  • çıkarırken sonuçlar şaşırtıcı olabilir, ancak ortak matematik duygusunu takip edin :
    • yaparken inf - infsonuç tanımsızdır NaN:;
    • yaparken inf - -infsonuç inf;
    • yaparken -inf - infsonuç -inf;
    • yaparken -inf - -inf, sonuç tanımsızdır: NaN.
  • eklerken, aynı şekilde şaşırtıcı olabilir:
    • yaparken inf + infsonuç inf;
    • yaparken inf + -infsonuç tanımsızdır NaN:;
    • yaparken -inf + infsonuç tanımsızdır NaN:;
    • yaparken -inf + -infsonuç -inf.
  • kullanmak math.pow, powya **da zor, olması gerektiği gibi davranmıyor. İki gerçek sayıyla sonuç, bir çift duyarlıklı şamandıra sığmayacak kadar yüksek olduğunda (sonsuzluk döndürmelidir), ancak giriş infveya olduğunda -infdoğru davranır ve ya infda döndürürse taşma istisnası atar 0.0. İkinci argüman olduğunda NaN, NaNilk argüman olmadığı sürece geri döner 1.0. Daha fazla sorun var, hepsi dokümanlarda ele alınmıyor .
  • math.expile aynı sorunları yaşıyor math.pow. Taşma için bunu düzeltmenin bir çözümü şuna benzer bir kod kullanmaktır:

    try:
        res = math.exp(420000)
    except OverflowError:
        res = float('inf')

notlar

Not 1: IEEE standardında tanımlandığı gibi, ek bir uyarı olarak, hesaplama sonucunuz az veya fazla taşarsa, sonuç bir düşük veya taşma hatası değil, pozitif veya negatif sonsuzluk: 1e308 * 10.0verim olacaktır inf.

Not 2: herhangi bir hesaplama nedeniyle NaNgetiri NaNve herhangi karşılaştırma NaNdahil NaNkendisi olduğunu false, kullanmak gerekir math.isnanbir numara gerçekten olup olmadığını belirlemek için işlev NaN.

Not 3: Python yazmayı desteklese de float('-NaN'), NaNdahili olarak oturum açma olmadığından işaret yok sayılır . Bölerseniz -inf / +inf, sonuç NaNdeğil -NaN(böyle bir şey yok).

Not 4: Python, derlendiği C veya Java kitaplığına dayandığı için yukarıdakilerden herhangi birine güvenmeye dikkat edin ve temeldeki tüm sistemler bu davranışı doğru bir şekilde gerçekleştirmez. Emin olmak istiyorsanız, hesaplamalarınızı yapmadan önce sonsuzluğu test edin.

¹) Son zamanlarda 3.2 sürümünden beri kullanılmaktadır .
²) Kayan noktalar pozitif ve negatif sıfırı destekler, dolayısıyla: x / float('inf')işaret ve -1 / float('inf')verimlerini -0.0, 1 / float(-inf)verimlerini -0.0, 1 / float('inf')verimlerini 0.0ve -1/ float(-inf)verimlerini korur 0.0. Buna ek olarak, 0.0 == -0.0birtrue , size gerçek olamayacak istemiyorsanız el işareti kontrol etmek zorunda.


11
Küçük bir nitpick: sonsuzluğa sahip her hesaplama sonsuzluğu vermez:-1 * float('infinity') == -inf
Evan Krall

4
Bu yüzden küçük bir nitpick olduğunu söyledim . Sonsuzluk ile çalışırken bir dakika boyunca bu işaretin tamamen göz ardı edileceğinden endişelendim ve diğer insanlar için açıklığa kavuşturmak istedim.
Evan Krall

12
Neredeyse: 1 / şamandıra ('sonsuz') == 0.0
Phil

3
@Phil: Sadece inf ile yapılan tüm hesaplamaların inf veya NaN ile sonuçlanmadığını göstermeye çalıştığımdan emin olmama rağmen, sadece yorumları okuyan başkalarına netleştirmek istedim, o 1 / float ('infinity (' infinity) ') == 0.0 doğrudur; çünkü, sonsuzluğa yaklaşırken, bölünmenin sonucu 0'a yaklaşır. Bunun sadece temel matematik olduğunu biliyorum, ama okuma yapanların sonuçun ne olduğunu anladığından emin olmak istedim ya da en azından neden olduğuna dair bir ipucu vardı.
Anthony Pace

1
Bu cevabın kabul edilen cevaptan çok daha iyi olduğunu hissediyorum.
Christian Herenz

3

Yani yapar C99 .

Tüm modern işlemciler tarafından kullanılan IEEE 754 kayan nokta temsili, pozitif sonsuzluk (işaret = 0, exp = ~ 0, frac = 0), negatif sonsuz (işaret = 1, exp = ~ 0, frac = 0) için ayrılmış birkaç özel bit desenine sahiptir. ) ve birçok NaN (Sayı Değil: exp = ~ 0, frac ≠ 0).

Endişelenmeniz gereken tek şey: bazı aritmetik kayan nokta istisnalarına / tuzaklarına neden olabilir, ancak bunlar sadece bu "ilginç" sabitlerle sınırlı değildir.


1
Yani benim aritmetik çok büyük bir inf olabilir?
Casebash

@Casebash Hayır, bir neden olur OverflowError.
wizzwizz4

2

Şimdiye kadar kimsenin bahsetmediği bir uyarı buldum. Pratik durumlarda sık sık ortaya çıkıp çıkmayacağını bilmiyorum, ama burada tamlık uğruna.

Genellikle, bir sayı modulo sonsuzluğunun hesaplanması kendisini bir kayan nokta olarak döndürür, ancak bir kesir modulo sonsuzluğu geri döner nan(bir sayı değil). İşte bir örnek:

>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan

Python hata izleyicide bir sorun bildirdim. Https://bugs.python.org/issue32968 adresinde görülebilir .

Güncelleme: Bu Python 3.8'de düzeltilecektir .


2

ÇOK KÖTÜ BİR CAVEAT: Zero Bölümü

bir 1/xkesirde, x = 1e-323öyle infama ne zaman x = 1e-324ya da az atıyorZeroDivisionError

>>> 1/1e-323
inf

>>> 1/1e-324
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero

bu yüzden dikkatli olun!

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.