Risposte:
Puoi ancora ottenere valori non numerici (NaN) da una semplice aritmetica che coinvolge inf:
>>> 0 * float("inf")
nan
Nota che normalmente non otterrai un infvalore attraverso i soliti calcoli aritmetici:
>>> 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')
Il infvalore è considerato un valore molto speciale con semantica insolita, quindi è meglio conoscere OverflowErrorimmediatamente un'eccezione, piuttosto che avere un infvalore iniettato silenziosamente nei calcoli.
**sembra un po 'difettoso. Quando trabocca di numeri reali, genera un errore, ma quando uno dei suoi operandi è info -inf, restituisce uno 0.0o inf. Così fa correttamente il lavoro quando l'ingresso è inifinty, ma non quando il risultato dovrebbe essere infinito.
L'implementazione di Python segue abbastanza bene lo standard IEEE-754 , che puoi usare come guida, ma si basa sul sistema sottostante su cui è stata compilata, quindi potrebbero verificarsi differenze di piattaforma . Recentemente¹, è stata applicata una correzione che consente "infinito" e "inf" , ma questo è di minore importanza qui.
Le seguenti sezioni si applicano ugualmente bene a qualsiasi linguaggio che implementa correttamente l'aritmetica in virgola mobile IEEE, non è specifico solo per Python.
Quando si tratta >di <operatori infinito e maggiore o minore di , valgono i seguenti elementi:
+infè superiore a-inf-infè inferiore a+inf +infnon è né superiore né inferiore a+inf-inf non è né superiore né inferiore a -infNaNè falso ( infnon è né superiore né inferiore a NaN)Se confrontato per l'uguaglianza, +infe +infsono uguali, come lo sono -infe -inf. Questo è un problema molto dibattuto e può sembrare controverso per te, ma è nello standard IEEE e Python si comporta proprio così.
Certo, +infè disuguale -infe tutto, incluso NaNse stesso, è disuguale NaN.
La maggior parte dei calcoli con infinito produrrà infinito, a meno che entrambi gli operandi siano infiniti, quando la divisione dell'operazione o il modulo, o con la moltiplicazione con zero, ci sono alcune regole speciali da tenere a mente:
NaN0.0o -0.0².NaN.inf - inf, il risultato è indefinito: NaN;inf - -inf, il risultato è inf;-inf - inf, il risultato è -inf;-inf - -inf, il risultato è indefinito: NaN.inf + inf, il risultato è inf;inf + -inf, il risultato è indefinito: NaN;-inf + inf, il risultato è indefinito: NaN;-inf + -inf, il risultato è -inf.math.pow, powo **è complicato, in quanto non si comporta come dovrebbe. Genera un'eccezione di overflow quando il risultato con due numeri reali è troppo alto per adattarsi a un float a doppia precisione (dovrebbe restituire l'infinito), ma quando l'input è info -inf, si comporta correttamente e restituisce info 0.0. Quando il secondo argomento è NaN, restituisce NaN, a meno che non sia il primo argomento 1.0. Ci sono più problemi, non tutti trattati nei documenti .math.expsoffre degli stessi problemi di math.pow. Una soluzione per risolvere questo problema di overflow è utilizzare un codice simile al seguente:
try:
res = math.exp(420000)
except OverflowError:
res = float('inf')Nota 1: come ulteriore avvertimento, quello come definito dallo standard IEEE, se il risultato del calcolo è under-overflow o overflow, il risultato non sarà un errore underflow o overflow, ma infinito positivo o negativo: 1e308 * 10.0rese inf.
Nota 2: poiché qualsiasi calcolo con NaNrendimenti NaNe qualsiasi confronto NaN, incluso NaNse stesso false, è necessario utilizzare la math.isnanfunzione per determinare se un numero è effettivamente NaN.
Nota 3: sebbene Python supporti la scrittura float('-NaN'), il segno viene ignorato, perché non esiste alcun segno NaNinternamente. Se dividi -inf / +inf, il risultato è NaNno -NaN(non esiste una cosa del genere).
Nota 4: fare attenzione a fare affidamento su quanto sopra, poiché Python si basa sulla libreria C o Java per la quale è stata compilata e non tutti i sistemi sottostanti implementano correttamente tutto questo comportamento. Se vuoi essere sicuro, prova all'infinito prima di fare i tuoi calcoli.
¹) Recentemente significa dalla versione 3.2 .
²) I punti fluttuanti supportano lo zero positivo e negativo, quindi: x / float('inf')mantiene il segno e-1 / float('inf') rendimenti -0.0, i 1 / float(-inf)rendimenti -0.0, i 1 / float('inf')rendimenti 0.0e i -1/ float(-inf)rendimenti 0.0. Inoltre, 0.0 == -0.0ètrue necessario controllare manualmente il segno se non si desidera che sia vero.
-1 * float('infinity') == -inf
Così fa C99 .
La rappresentazione in virgola mobile IEEE 754 utilizzata da tutti i processori moderni ha diversi schemi di bit speciali riservati per l'infinito positivo (segno = 0, exp = ~ 0, frac = 0), l'infinito negativo (segno = 1, exp = ~ 0, frac = 0 ) e molti NaN (Not a Number: exp = ~ 0, frac ≠ 0).
Tutto ciò di cui devi preoccuparti: un po 'di aritmetica può causare eccezioni / trappole in virgola mobile, ma quelle non sono limitate solo a queste costanti "interessanti".
OverflowError.
Ho trovato un avvertimento che nessuno finora ha menzionato. Non so se si presenterà spesso in situazioni pratiche, ma qui è per completezza.
Di solito, il calcolo di un numero modulo infinito restituisce se stesso come un valore a virgola mobile, ma una frazione modulo infinito ritorna nan(non un numero). Ecco un esempio:
>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan
Ho presentato un problema sul tracker dei bug di Python. Può essere visto su https://bugs.python.org/issue32968 .
Aggiornamento: questo sarà risolto in Python 3.8 .
UNA CAVEAT MOLTO MALE: Division by Zero
in una 1/xfrazione, fino a che x = 1e-323lo è infma quando x = 1e-324o poco gettaZeroDivisionError
>>> 1/1e-323
inf
>>> 1/1e-324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
quindi sii cauto!
1e309verrà interpretata come+infe-1e309verrà interpretata come-inf.