OverflowError: long int trop grand pour se convertir à flotter en python

j'ai essayé de calculer la distribution de poisson en python comme suit:

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

idx varie de 0

Mais je suis d' OverflowError: long int too large to convert to float

j'ai essayé de convertir départ enfloat mais pas de résultats.

18
demandé sur Martijn Pieters 2013-04-23 20:20:50

4 réponses

Factorielles obtenir grand rapide:

>>> math.factorial(170)
7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000L

Notez le L; la factorielle de 170 est encore modulable pour un float:

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

mais le prochain factoriel est trop grand:

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

Vous decimal module; les calculs seront plus lents, mais le Decimal() classe peut gérer les factorielles de cette taille:

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

vous devrez utiliser Decimal() valeurs à travers:

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)
22
répondu Martijn Pieters 2013-04-23 16:44:30

quand idx devient grand soit le math.pow et/ou math.factorial va devenir démesurément grand et ne pourra pas se convertir à une valeur flottante (idx=1000 déclenche l'erreur sur mon ordinateur 64 bits). Tu ne dois pas utiliser les maths.pow fonctionne car il déborde plus tôt que le construit dans ** opérateur car il essaie de garder une plus grande précision en convertissant plus tôt les flotteurs. En outre, vous pouvez envelopper chaque appel de fonction dans un Decimal objet pour plus de précision.

une autre approche lorsque traiter de très grands nombres est de travailler dans l'échelle logarithmique. Prendre le log de chaque valeur (ou calculer la version log de chaque valeur) et effectuer toutes les opérations nécessaires avant de prendre l'exponentiation des résultats. Cela permet à vos valeurs de quitter temporairement l'espace du domaine flottant tout en calculant avec précision une réponse finale qui se trouve dans le domaine flottant.

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)

cela reste dans le domaine log jusqu'à la toute fin de sorte que vos nombres peuvent devenir très, très grand avant tu vas avoir des problèmes de débordement.

4
répondu Pyrce 2017-02-24 18:36:54

essayez d'utiliser la bibliothèque décimale. Il prétend en précision arbitraire.

from decimal import Decimal

en outre, vous n'avez pas besoin d'utiliser math.pow. pow est en construction.

3
répondu xylon97 2013-04-23 16:25:53

scipy module pourrait vous aider.

scipy.misc.factoriel est une fonction factorielle qui peut utiliser l'approximation de la fonction gamma pour calculer le factoriel, et renvoie le résultat en utilisant des points flottants.

import numpy
from scipy.misc import factorial

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

Donne:

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

Il y a aussi un module pour calculer les distributions de Poisson. Par exemple:

import numpy
from scipy.stats import poisson

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

Donne:

[ 0.04978707  0.14936121  0.22404181  0.22404181  0.16803136  0.10081881
  0.05040941  0.02160403  0.00810151  0.0027005 ]
0
répondu Charles Brunet 2013-04-23 16:40:39