Zauważ, że stała 1e309będzie interpretowana jako +infi -1e309będzie interpretowana jako -inf.
Chris Taylor
Odpowiedzi:
97
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**24.0>>> _**216.0>>> _**2256.0>>> _**265536.0>>> _**24294967296.0>>> _**21.8446744073709552e+19>>> _**23.4028236692093846e+38>>> _**21.157920892373162e+77>>> _**21.3407807929942597e+154>>> _**2Traceback(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ń.
Proste dodawanie zmiennoprzecinkowe, mnożenie itp. Z radością wygeneruje inf: f = 1.3407807929942597e + 154; f * f => inf. Wydaje się raczej wyjątkiem **, aby podnieść błąd OverflowError.
eregon
@eregon **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ść.
Abel
2
@Abel To nie jest buggy. Przepełnienie oznacza, że liczba jest bardzo duża. Zbyt duży, aby go reprezentować, ale wciąż znacznie mniejszy niż nieskończoność. Umieszczenie nieskończoności w takim miejscu może być przydatne dla obsługi wyjątków dla konkretnej logiki aplikacji, ale ogólnie byłoby niepoprawne dla Pythona.
Lutz Prechelt
6
@Lutz, jeśli pojawia się jako pomnożenie, to nadal jest niespójne zachowanie. Z pewnością duży * duży też nie jest nieskończonością.
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.
Porównanie nierówności
W przypadku operatorów nieskończoności i operatorów większych niż >lub mniejszych <liczy się:
wszelkie porównania z tym NaNsą fałszywe ( infnie są ani wyższe, ani niższe niż NaN)
Porównanie dla równości
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.
Obliczenia z nieskończonością
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:
pomnożony przez zero, dla którego wynik jest niezdefiniowany, daje wynik NaN
dzieląc dowolną liczbę (oprócz samej nieskończoności) przez nieskończoność, która daje 0.0lub -0.0².
dzieląc (w tym modulo) dodatnią lub ujemną nieskończoność przez dodatnią lub ujemną nieskończoność, wynik jest niezdefiniowany, więc NaN.
odejmując wyniki mogą być zaskakujące, ale kieruj się zdrowym rozsądkiem :
gdy robi inf - inf, wynik jest niezdefiniowany: NaN;
kiedy to robi inf - -inf, wynik jest inf;
kiedy to robi -inf - inf, wynik jest -inf;
gdy robi -inf - -inf, wynik jest niezdefiniowany: NaN.
podczas dodawania może być podobnie zaskakujące:
kiedy to robi inf + inf, wynik jest inf;
gdy robi inf + -inf, wynik jest niezdefiniowany: NaN;
gdy robi -inf + inf, wynik jest niezdefiniowany: NaN;
kiedy to robi -inf + -inf, wynik jest -inf.
za pomocą 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)exceptOverflowError:
res = float('inf')
Notatki
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ą.
Mały nitpick: nie każde obliczenie z nieskończonością daje nieskończoność:-1 * float('infinity') == -inf
Evan Krall
4
Właśnie dlatego powiedziałem, że to mała nitpick. Przez minutę martwiłeś mnie, że znak będzie całkowicie ignorowany podczas pracy z nieskończonością, a ja chciałem wyjaśnić innym ludziom.
Evan Krall,
12
Cóż, prawie: 1 / float ('infinity') == 0,0
Phil
3
@Phil: Chociaż jestem prawie pewien, że starałeś się tylko pokazać, że nie wszystkie obliczenia z inf powodują inf lub NaN, chciałem tylko wyjaśnić innym, którzy mogą czytać komentarze, że 1 / float ('infinity ') == 0,0 jest prawdą; ponieważ, gdy zbliżacie się do nieskończoności, wynik podziału zbliża się do 0. Wiem, że to tylko podstawowy rachunek różniczkowy, ale chciałem mieć pewność, że czytający rozumieją lub przynajmniej mają pojęcie, dlaczego wynik jest taki, jaki jest.
Anthony Pace
1
Mam wrażenie, że ta odpowiedź jest znacznie lepsza niż odpowiedź zaakceptowana.
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.
Więc jeśli moja arytmetyka jest zbyt duża, może stać się inf?
Casebash
@Casebash Nie, spowoduje to OverflowError.
wizzwizz4,
2
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 importFraction>>>from math import inf
>>>3% inf
3.0>>>3.5% inf
3.5>>>Fraction('1/3')% inf
nan
1e309
będzie interpretowana jako+inf
i-1e309
będzie interpretowana jako-inf
.Odpowiedzi:
Nadal można uzyskać wartości inne niż liczba (NaN) z prostej arytmetyki obejmującej
inf
:Zauważ, że zwykle nie otrzymasz
inf
wartości poprzez zwykłe obliczenia arytmetyczne:inf
Wartość jest uważane za bardzo szczególny stosunek z niezwykłymi semantyki, więc lepiej wiedzieć oOverflowError
razu przez wyjątek, a nie posiadająceinf
wartość cicho wtryskiwanego do swoich obliczeń.źródło
**
wydaje się być trochę powalony . Kiedy przepełnia się liczbami rzeczywistymi, generuje błąd, ale gdy którykolwiek z jego operandów jestinf
lub-inf
, zwraca albo0.0
alboinf
. 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.
Porównanie nierówności
W przypadku operatorów nieskończoności i operatorów większych niż
>
lub mniejszych<
liczy się:+inf
jest wyższa niż-inf
-inf
jest mniejsza niż+inf
+inf
nie jest ani wyższy, ani niższy niż+inf
-inf
nie jest ani wyższy, ani niższy niż-inf
NaN
są fałszywe (inf
nie są ani wyższe, ani niższe niżNaN
)Porównanie dla równości
W porównaniu do równości
+inf
i+inf
są równe, tak jak-inf
i-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,
+inf
jest nierówny,-inf
a wszystko, w tym iNaN
sam, jest nierówneNaN
.Obliczenia z nieskończonością
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:
NaN
0.0
lub-0.0
².NaN
.inf - inf
, wynik jest niezdefiniowany:NaN
;inf - -inf
, wynik jestinf
;-inf - inf
, wynik jest-inf
;-inf - -inf
, wynik jest niezdefiniowany:NaN
.inf + inf
, wynik jestinf
;inf + -inf
, wynik jest niezdefiniowany:NaN
;-inf + inf
, wynik jest niezdefiniowany:NaN
;-inf + -inf
, wynik jest-inf
.math.pow
,pow
lub**
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 toinf
lub-inf
, zachowuje się poprawnie i zwraca alboinf
albo0.0
. Gdy drugim argumentem jestNaN
, zwracaNaN
, chyba że pierwszym argumentem jest1.0
. Jest więcej problemów, nie wszystkie omówione w dokumentach .math.exp
cierpi na takie same problemy jakmath.pow
. Rozwiązaniem tego problemu w przypadku przepełnienia jest użycie kodu podobnego do tego:Notatki
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.0
dajeinf
.Uwaga 2: ponieważ wszelkie obliczenia ze
NaN
zwrotamiNaN
i wszelkie porównania doNaN
, w tymNaN
samego siebiefalse
, należy użyćmath.isnan
funkcji do ustalenia, czy liczba rzeczywiście jest liczbąNaN
.Uwaga 3: mimo że Python obsługuje pisanie
float('-NaN')
, znak jest ignorowany, ponieważ nie istniejeNaN
wewnętrzny znak . Jeśli się podzielisz-inf / +inf
, wynik jest następującyNaN
: 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')
daje0.0
i-1/ float(-inf)
daje0.0
. Ponadto,0.0 == -0.0
jesttrue
, trzeba ręcznie sprawdzić znak, jeśli nie ma to być prawdą.źródło
-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.
źródło
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: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 .
źródło
w
1/x
frakcji, dox = 1e-323
tego jestinf
jednak przyx = 1e-324
lub nieco generujeZeroDivisionError
więc bądź ostrożny!
źródło