2013-04-23 33 views
18

tôi đã cố gắng để tính toán phân phối Poisson trong python như sau:OverflowError: dài int quá lớn để chuyển đổi thả nổi trong python

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

idx dao động từ 0

Nhưng tôi đã OverflowError: long int too large to convert to float

tôi cố gắng chuyển đổi khởi hành thành float nhưng không có kết quả nào.

+0

thừa nhận * thực sự * lớn, * thực sự * nhanh –

+1

gì là giá trị của idx khi bạn nhấn lỗi này? – Pyrce

+0

Khi bạn muốn tính toán một thừa, tính toán đó là logarit thay – zehelvion

Trả lời

3

Thử sử dụng thư viện thập phân. Nó tuyên bố để hỗ trợ độ chính xác tùy ý.
from decimal import Decimal

Ngoài ra, bạn không cần sử dụng math.pow. pow được tích hợp sẵn.

+0

Hi guys tôi cố gắng sử dụng số thập phân hoặc scipy nhưng tôi đã nhận ImportError: Không có mô-đun tên scipy.stats lỗi tương tự cho số thập phân – user2312186

+0

phiên bản nào là bạn đang chạy? Thư viện 'thập phân' được cho là tiêu chuẩn cho tất cả. có lẽ bạn đã xóa nó. cài đặt lại python và nó sẽ sửa chữa nó. đối với scipy, nó là một gói của bên thứ ba, vì vậy bạn sẽ phải tải xuống từ scipy.org – xylon97

+0

Tôi đã cài đặt scipy và nó hoạt động tốt – user2312186

21

thừa được lớn thật nhanh:

>>> math.factorial(170) 
7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000L 

Lưu ý L; giai thừa của 170 vẫn còn chuyển thành một float:

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

nhưng thừa tiếp theo là quá lớn:

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

Bạn thể sử dụng decimal module; tính toán sẽ chậm hơn, nhưng lớp Decimal() có thể xử lý thừa kích thước này:

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

Bạn sẽ phải sử dụng Decimal() giá trị suốt:

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

Lớp số lớn trong Python được gọi là gì? bởi vì '170! 'cao hơn giới hạn của số nguyên 64 bit. Tôi cho rằng loại này bị ép buộc? Nếu vậy, tại sao 'L' vẫn được nối vào cuối? –

+1

@HunterMcMillen: Các số nguyên dài Python chỉ bị giới hạn bởi cấp phát bộ nhớ OS. 'L' biểu thị rằng chúng ta đã vượt quá kích thước nguyên C tối đa cho nền tảng (64-bit trong trường hợp của tôi) để hiển thị các số nguyên dài đang được sử dụng; quá trình chuyển đổi là tự động. Xem http://docs.python.org/2/library/stdtypes.html#numeric-types-int-float-long-complex –

+0

Ahh, tôi hiểu. Hầu hết các ngôn ngữ khác có 'BigInteger' hoặc một cái gì đó tương tự. Cảm ơn. –

4

Khi idx được lớn hoặc là math.pow và/hoặc math.factorial sẽ trở nên cực kỳ lớn và không thể chuyển đổi thành giá trị thả nổi (idx=1000 kích hoạt lỗi trên máy 64 bit của tôi). Bạn sẽ không muốn sử dụng hàm math.pow khi nó tràn sớm hơn toán tử được xây dựng trong ** vì nó cố gắng giữ độ chính xác cao hơn bằng cách chuyển đổi float trước đó. Ngoài ra, bạn có thể bọc từng cuộc gọi chức năng trong một đối tượng Decimal để có độ chính xác cao hơn.

Một cách tiếp cận khác khi xử lý các số rất lớn là làm việc trong thang đo log. Lấy nhật ký của mọi giá trị (hoặc tính toán phiên bản nhật ký của mỗi giá trị) và thực hiện tất cả các hoạt động được yêu cầu trước khi tính lũy thừa các kết quả. Điều này cho phép các giá trị của bạn tạm thời rời khỏi không gian tên miền nổi trong khi vẫn tính toán chính xác câu trả lời cuối cùng nằm trong miền nổi.

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) 

Điều này nằm trong miền nhật ký cho đến khi kết thúc để số của bạn có thể rất, rất lớn trước khi bạn gặp phải sự cố tràn.

+0

Tôi nghĩ rằng '3 ** idx => math.log (3) * math.log (idx)' nên là '3 ** idx => math.log (3) * idx' –

+0

Opps, vâng bạn là chính xác. – Pyrce

0

Mô-đun scipy có thể giúp bạn.

scipy.misc.factorial là hàm giai thừa có thể sử dụng tính xấp xỉ hàm gamma để tính giai thừa và trả về kết quả bằng cách sử dụng dấu phẩy động.

import numpy 
from scipy.misc import factorial 

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

Cung cấp:

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

Ngoài ra còn có một module to calculate Poisson distributions. Ví dụ:

import numpy 
from scipy.stats import poisson 

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

Cung cấp:

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

+1 cho 'scipy.stats', nhưng các chức năng cung cấp scipy giai thừa sẽ vẫn' inf' ra ở đối số lớn. – DSM

+0

Cảm ơn. Tôi sẽ tạo ra số Poisson như tạo ra thời gian gói trong mạng. Làm thế nào tôi có thể sử dụng chức năng này để tạo ra một số Poisson mỗi liên tục? – user2312186

Các vấn đề liên quan