2013-04-23 14 views
18

ho cercato di calcolare la distribuzione di Poisson in Python, come di seguito:OverflowError: long int troppo grande per la conversione a galleggiare in python

p = math.pow(3,idx) 
depart = math.exp(-3) * p 
depart = depart/math.factorial(idx) 

IDX varia da 0

Ma ho avuto OverflowError: long int too large to convert to float

I provato a convertire partire a float ma nessun risultato.

+0

fattoriale ottiene * veramente * grande, * veramente * veloce –

+1

Qual è il valore di IDX quando si preme questo errore? – Pyrce

+0

Quando si desidera calcolare un fattoriale, calcolare è logaritmo invece – zehelvion

risposta

3

Provare a utilizzare la libreria decimale. Sostiene di supportare precisione arbitraria.
from decimal import Decimal

Inoltre, non c'è bisogno di usare math.pow. pow è integrato.

+0

Ciao ragazzi Ho cercato di usare decimale o SciPy ma ho avuto ImportError: No module named scipy.stats lo stesso errore, per decimali – user2312186

+0

quale versione stai in esecuzione? la libreria 'decimal' dovrebbe essere standard per tutti. forse l'hai cancellato. reinstallare python e lo risolverà. per quanto riguarda scipy, è un pacchetto di terze parti, quindi dovrai scaricarlo da scipy.org – xylon97

+0

ho installato scipy e funziona bene – user2312186

21

fattoriali ottenere grandi veloce reale:

>>> math.factorial(170) 
7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000L 

Annotare il L; il fattoriale di 170 è ancora convertibile ad un galleggiante:

>>> float(math.factorial(170)) 
7.257415615307999e+306 

ma il prossimo fattoriale è troppo grande:

>>> float(math.factorial(171)) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
OverflowError: long int too large to convert to float 

Si potrebbe utilizzare il decimal module; calcoli saranno più lenti, ma la classe Decimal() in grado di gestire fattoriali queste dimensioni:

>>> from decimal import Decimal 
>>> Decimal(math.factorial(171)) 
Decimal('1241018070217667823424840524103103992616605577501693185388951803611996075221691752992751978120487585576464959501670387052809889858690710767331242032218484364310473577889968548278290754541561964852153468318044293239598173696899657235903947616152278558180061176365108428800000000000000000000000000000000000000000') 

dovrete utilizzare Decimal() valori tutto:

from decimal import * 

with localcontext() as ctx: 
    ctx.prec = 32 # desired precision 
    p = ctx.power(3, idx) 
    depart = ctx.exp(-3) * p 
    depart /= math.factorial(idx) 
+0

Come si chiama la grande classe numerica in Python? perché '170!' è ben al di sopra dei limiti di un numero intero a 64 bit. Presumo che il tipo sia forzato a quello? Se è così, perché il 'L 'è ancora aggiunto alla fine? –

+1

@HunterMcMillen: gli interi lunghi Python sono limitati solo dall'allocazione della memoria del sistema operativo. La 'L' significa che ci siamo spostati oltre la dimensione massima C integer per la piattaforma (64 bit nel mio caso) per mostrare che vengono usati interi long; la transizione è automatica. Vedi http://docs.python.org/2/library/stdtypes.html#numeric-types-int-float-long-complex –

+0

Ah, capisco. La maggior parte delle altre lingue ha 'BigInteger' o qualcosa di simile. Grazie. –

4

Quando idx diventa grande sia il math.pow e/o la math.factorial diventerà incredibilmente grande e non sarà in grado di convertire in un valore fluttuante (idx=1000 attiva l'errore sulla mia macchina a 64 bit). Non vorrete utilizzare la funzione math.pow perché si riversa prima dell'operatore ** integrato perché prova a mantenere una maggiore precisione mediante la conversione float precedente. Inoltre è possibile racchiudere ciascuna chiamata di funzione in un oggetto Decimal per una maggiore precisione.

Un altro approccio quando si gestiscono numeri molto grandi è di lavorare nella scala di registro. Prendi il log di ogni valore (o calcola la versione del log di ciascun valore) ed esegui tutte le operazioni richieste prima di prendere l'esponenziazione dei risultati. Ciò consente ai valori di lasciare temporaneamente lo spazio del dominio mobile mentre calcola ancora accuratamente una risposta finale che si trova all'interno del dominio mobile.

3 ** idx => math.log(3) * idx 
math.exp(-3) * p => -3 + math.log(p) 
math.factorial(idx) => sum(math.log(ii) for ii in range(1, idx)) 
... 
math.exp(result) 

Questo rimane nel dominio di registro fino alla fine in modo che i numeri possono diventare molto, molto grande, prima ti ha colpito problemi di overflow.

+0

Penso che '3 ** idx => math.log (3) * math.log (idx)' dovrebbe essere '3 ** idx => math.log (3) * idx' –

+0

Opps, sì, hai ragione. – Pyrce

0

Il modulo scipy potrebbe aiutarti.

scipy.misc.factorial è una funzione fattoriale che può utilizzare l'approssimazione della funzione gamma per calcolare il fattoriale e restituisce il risultato utilizzando i punti mobili.

import numpy 
from scipy.misc import factorial 

i = numpy.arange(10) 
print(numpy.exp(-3) * 3**i/factorial(i)) 

Dà:

[ 0.04978707 0.14936121 0.22404181 0.22404181 0.16803136 0.10081881 
    0.05040941 0.02160403 0.00810151 0.0027005 ] 

C'è anche una module to calculate Poisson distributions. Per esempio:

import numpy 
from scipy.stats import poisson 

i = numpy.arange(10) 
p = poisson(3) 
print(p.pmf(i)) 

Dà:

[ 0.04978707 0.14936121 0.22404181 0.22404181 0.16803136 0.10081881 
    0.05040941 0.02160403 0.00810151 0.0027005 ] 
+0

+1 per 'scipy.stats', ma la funzione fattoriale scipy offre ancora' inf' a grande argomento. – DSM

+0

Grazie. Ho intenzione di generare numeri di Poisson come generazione del tempo di pacchetto nella rete. Come posso usare questa funzione per generare continuamente un numero di Poisson? – user2312186