Odpowiedzi:
Nadal można uzyskać wartości inne niż liczba (NaN) z prostej arytmetyki obejmującej inf:
>>> 0 * float("inf")
nan
Zauważ, że zwykle nie otrzymasz infwartości poprzez zwykłe obliczenia arytmetyczne:
>>> 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')
infWartość jest uważane za bardzo szczególny stosunek z niezwykłymi semantyki, więc lepiej wiedzieć o OverflowErrorrazu przez wyjątek, a nie posiadające infwartość cicho wtryskiwanego do swoich obliczeń.
**wydaje się być trochę powalony . Kiedy przepełnia się liczbami rzeczywistymi, generuje błąd, ale gdy którykolwiek z jego operandów jest influb -inf, zwraca albo 0.0albo inf. Więc to nie działa prawidłowo, jeśli wejście jest inifinty, ale nie wtedy, gdy wynik powinien być nieskończoność.
Implementacja Pythona całkiem dobrze podąża za standardem IEEE-754 , którego można użyć jako przewodnika, ale zależy on od systemu bazowego, na którym został skompilowany, więc mogą wystąpić różnice między platformami . Ostatnio¹ została zastosowana poprawka, która dopuszcza zarówno „nieskończoność”, jak i „inf” , ale ma to niewielkie znaczenie.
Poniższe sekcje odnoszą się równie dobrze do każdego języka, który poprawnie implementuje arytmetykę zmiennoprzecinkową IEEE, nie jest ona specyficzna tylko dla Pythona.
W przypadku operatorów nieskończoności i operatorów większych niż >lub mniejszych <liczy się:
+infjest wyższa niż-inf-infjest mniejsza niż+inf +infnie jest ani wyższy, ani niższy niż+inf-inf nie jest ani wyższy, ani niższy niż -infNaNsą fałszywe ( infnie są ani wyższe, ani niższe niż NaN)W porównaniu do równości +infi +infsą równe, tak jak -infi -inf. Jest to bardzo dyskutowana kwestia i może ci się wydawać kontrowersyjna, ale jest w standardzie IEEE i Python zachowuje się w ten sposób.
Oczywiście, +infjest nierówny, -infa wszystko, w tym i NaNsam, jest nierówne NaN.
Większość obliczeń z nieskończonością da nieskończoność, chyba że oba operandy są nieskończonością, gdy podział operacji lub modulo, lub z mnożeniem przez zero, należy pamiętać o kilku szczególnych zasadach:
NaN0.0lub -0.0².NaN.inf - inf, wynik jest niezdefiniowany: NaN;inf - -inf, wynik jest inf;-inf - inf, wynik jest -inf;-inf - -inf, wynik jest niezdefiniowany: NaN.inf + inf, wynik jest inf;inf + -inf, wynik jest niezdefiniowany: NaN;-inf + inf, wynik jest niezdefiniowany: NaN;-inf + -inf, wynik jest -inf.math.pow, powlub **jest trudne, ponieważ nie zachowuje się tak jak powinno. Zgłasza wyjątek przepełnienia, gdy wynik z dwiema liczbami rzeczywistymi jest zbyt wysoki, aby zmieścić liczbę zmiennoprzecinkową o podwójnej precyzji (powinien zwrócić nieskończoność), ale gdy dane wejściowe to influb -inf, zachowuje się poprawnie i zwraca albo infalbo 0.0. Gdy drugim argumentem jest NaN, zwraca NaN, chyba że pierwszym argumentem jest 1.0. Jest więcej problemów, nie wszystkie omówione w dokumentach .math.expcierpi na takie same problemy jak math.pow. Rozwiązaniem tego problemu w przypadku przepełnienia jest użycie kodu podobnego do tego:
try:
res = math.exp(420000)
except OverflowError:
res = float('inf')Uwaga 1: jako dodatkowe zastrzeżenie, że zgodnie z definicją standardu IEEE, jeśli wynik obliczeń jest niedopełniony lub przepełniony, wynikiem nie będzie błąd niedopełnienia lub przepełnienia, ale dodatnia lub ujemna nieskończoność: 1e308 * 10.0daje inf.
Uwaga 2: ponieważ wszelkie obliczenia ze NaNzwrotami NaNi wszelkie porównania do NaN, w tym NaNsamego siebie false, należy użyć math.isnanfunkcji do ustalenia, czy liczba rzeczywiście jest liczbą NaN.
Uwaga 3: mimo że Python obsługuje pisanie float('-NaN'), znak jest ignorowany, ponieważ nie istnieje NaNwewnętrzny znak . Jeśli się podzielisz -inf / +inf, wynik jest następujący NaN: nie -NaN(nie ma czegoś takiego).
Uwaga 4: staraj się polegać na jednym z powyższych elementów, ponieważ Python opiera się na bibliotece C lub Java, dla której został skompilowany, i nie wszystkie systemy bazowe poprawnie wdrażają to zachowanie. Jeśli chcesz się upewnić, przetestuj nieskończoność przed wykonaniem obliczeń.
¹) Ostatnio oznacza, że od wersji 3.2 .
²) Punkty zmiennoprzecinkowe obsługują zero dodatnie i ujemne, więc: x / float('inf')zachowuje swój znak i -1 / float('inf')daje -0.0, 1 / float(-inf)daje -0.0, 1 / float('inf')daje 0.0i -1/ float(-inf)daje 0.0. Ponadto, 0.0 == -0.0jesttrue , trzeba ręcznie sprawdzić znak, jeśli nie ma to być prawdą.
-1 * float('infinity') == -inf
Podobnie C99 .
Reprezentacja zmiennoprzecinkowa IEEE 754 używana przez wszystkie nowoczesne procesory ma kilka specjalnych wzorów bitów zarezerwowanych dla dodatniej nieskończoności (znak = 0, exp = ~ 0, frac = 0), ujemna nieskończoność (znak = 1, exp = ~ 0, frac = 0 ) i wiele NaN (Not a Number: exp = ~ 0, frac ≠ 0).
Wszystko, o co musisz się martwić: pewna arytmetyka może powodować wyjątki / pułapki zmiennoprzecinkowe, ale nie są one ograniczone tylko do tych „interesujących” stałych.
OverflowError.
Znalazłem zastrzeżenie, o którym nikt dotąd nie wspomniał. Nie wiem, czy będzie się często pojawiał w praktycznych sytuacjach, ale tutaj jest to ze względu na kompletność.
Zwykle obliczenie liczby modulo nieskończoności zwraca się jako liczba zmiennoprzecinkowa, ale ułamek modulo nieskończoności zwraca nan(nie liczbę). Oto przykład:
>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan
Złożyłem problem w narzędziu do śledzenia błędów w Pythonie. Można to zobaczyć na https://bugs.python.org/issue32968 .
Aktualizacja: zostanie to naprawione w Pythonie 3.8 .
BARDZO ZŁA CAVEAT: Podział przez zero
w 1/xfrakcji, do x = 1e-323tego jest infjednak przy x = 1e-324lub nieco generujeZeroDivisionError
>>> 1/1e-323
inf
>>> 1/1e-324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
więc bądź ostrożny!
1e309będzie interpretowana jako+infi-1e309będzie interpretowana jako-inf.