2013-04-23 8 views
18

Próbowałem obliczyć rozkład Poissona w Pythonie jak poniżej:OverflowError: long int zbyt duże, aby przekształcić się unosić w Pythonie

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

idx waha się od 0

Ale mam OverflowError: long int too large to convert to float

I próbowałem przekonwertować odejść do float, ale bez wyników.

+0

Silnia dostaje * naprawdę * duży, * naprawdę * szybko –

+1

Co jest wartością idx po trafieniu tego błędu? – Pyrce

+0

Gdy chcesz obliczyć silnię, obliczyć logarytm to zamiast – zehelvion

Odpowiedz

3

Spróbuj użyć biblioteki dziesiętnej. Twierdzi, że wspiera arbitralną precyzję.
from decimal import Decimal

Ponadto, nie trzeba używać math.pow. pow jest wbudowany.

+0

Hi guys Próbuję użyć po przecinku lub scipy ale mam ImportError: nie moduł o nazwie scipy.stats ten sam błąd co do dziesiętnych – user2312186

+0

wersja Czy jesteś bieganie? Biblioteka "dziesiętna" ma być standardem dla wszystkich. być może usunąłeś to. ponownie zainstalować python i to naprawi. jak dla scipy, jest to pakiet zewnętrzny, więc będziesz musiał go pobrać z scipy.org – xylon97

+0

Zainstalowałem scipy i działa dobrze – user2312186

21

silni uzyskać dużą naprawdę szybko:

>>> math.factorial(170) 
7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000L 

Zanotować L; silnia 170 jest nadal convertable do pływaka:

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

ale następnego silnia jest zbyt duży:

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

Ty mógłby użyć decimal module; Obliczenia będą wolniejsze, ale klasa Decimal() silni może obsłużyć tej wielkości:

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

będziesz musiał użyć całej Decimal() wartości:

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

Jak nazywa się duża klasa liczb w języku Python? ponieważ '170!' znacznie przekracza ograniczenia 64-bitowej liczby całkowitej. Zakładam, że typ jest do tego zmuszony? Jeśli tak, dlaczego "L" wciąż jest dołączone do końca? –

+1

@HunterMcMillen: długie liczby w języku Python są ograniczone tylko przez przydzielanie pamięci systemu operacyjnego. 'L' oznacza, że ​​przekroczyliśmy maksymalny rozmiar liczby całkowitej C dla platformy (w moim przypadku 64-bitowe), aby pokazać długie liczby całkowite; przejście jest automatyczne. Zobacz http://docs.python.org/2/library/stdtypes.html#numeric- typeses-int-float-long-complex –

+0

Ahh, rozumiem. Większość innych języków ma 'BigInteger' lub coś podobnego. Dzięki. –

4

Kiedy idx dostaje duży albo math.pow i/lub math.factorial stanie się niesamowicie duży i nie będzie w stanie przekonwertować na wartość zmiennoprzecinkową (idx=1000 powoduje błąd na moim komputerze 64-bitowym). Nie powinieneś używać funkcji math.pow, ponieważ przepełnia ona wcześniej niż wbudowany operator **, ponieważ stara się zachować wyższą precyzję przez wcześniejsze przekształcenie typu float. Dodatkowo możesz zawijać każde wywołanie funkcji w obiekcie Decimal, aby uzyskać większą precyzję.

Innym podejściem do pracy z bardzo dużymi liczbami jest praca w skali logarytmicznej. Wykonaj dziennik każdej wartości (lub oblicz wersję dziennika każdej wartości) i wykonaj wszystkie wymagane operacje przed przystąpieniem do potęgowania wyników. Dzięki temu wartości tymczasowo opuszczają przestrzeń domenową, a jednocześnie precyzyjnie obliczają ostateczną odpowiedź, która leży w domenie pływającej.

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) 

Pozostaje w domenie logu do samego końca, dzięki czemu Twoje numery mogą być bardzo, bardzo duże, zanim trafisz na problemy z przepełnieniem.

+0

Myślę, że '3 ** idx => math.log (3) * math.log (idx)' powinno być '3 ** idx => math.log (3) * idx' –

+0

Opps, tak masz rację. – Pyrce

0

Moduł scipy może pomóc.

scipy.misc.factorial to funkcja silni, która może użyć aproksymacji funkcji gamma do obliczenia silni i zwraca wynik za pomocą liczb zmiennoprzecinkowych.

import numpy 
from scipy.misc import factorial 

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

Daje:

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

Istnieje również module to calculate Poisson distributions. Na przykład:

import numpy 
from scipy.stats import poisson 

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

Daje:

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

+1 dla 'scipy.stats', ale oferty scipy funkcji silni będą nadal' inf' na dużą argumentację. – DSM

+0

Dzięki. Mam zamiar generować liczby Poissona jako generujące czas pakietów w sieci. Jak mogę użyć tej funkcji do ciągłego generowania liczby Poissona? – user2312186

Powiązane problemy