OverflowError:long int太大,无法在python中转换为float

use*_*186 23 python overflow factorial

我试图在python中计算泊松分布如下:

p = math.pow(3,idx)
depart = math.exp(-3) * p 
depart = depart / math.factorial(idx)
Run Code Online (Sandbox Code Playgroud)

idx范围从0

但是我得到了 OverflowError: long int too large to convert to float

我试图将转换转换为float但没有结果.

Mar*_*ers 28

因子变得非常快:

>>> math.factorial(170)
7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000L
Run Code Online (Sandbox Code Playgroud)

注意L; 阶乘170仍可转换为浮动:

>>> float(math.factorial(170))
7.257415615307999e+306
Run Code Online (Sandbox Code Playgroud)

但下一个因素太大了:

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

可以使用这个decimal模块 ; 计算会更慢,但是Decimal()类可以处理这个大小的阶乘:

>>> from decimal import Decimal
>>> Decimal(math.factorial(171))
Decimal('1241018070217667823424840524103103992616605577501693185388951803611996075221691752992751978120487585576464959501670387052809889858690710767331242032218484364310473577889968548278290754541561964852153468318044293239598173696899657235903947616152278558180061176365108428800000000000000000000000000000000000000000')
Run Code Online (Sandbox Code Playgroud)

你必须Decimal()在整个过程中使用值:

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)
Run Code Online (Sandbox Code Playgroud)

  • @HunterMcMillen:Python长整数仅受操作系统内存分配的限制。“ L”表示我们超出了平台的最大C整数大小(在我的情况下为64位)以显示正在使用长整数;过渡是自动的。参见http://docs.python.org/2/library/stdtypes.html#numeric-types-int-float-long-complex (2认同)

Pyr*_*rce 5

当idx变大时,idx和/或math.pow将变得非常大并且无法转换为浮动值(math.factorial在我的64位机器上触发错误).你不想使用math.pow函数,因为它比内置idx=1000运算符更早溢出,因为它试图通过先前的浮点转换来保持更高的精度.此外,您可以将每个函数调用包装在**对象中以获得更高的精度.

处理非常大数字时的另一种方法是在对数范围内工作.获取每个值的日志(或计算每个值的日志版本)并执行所有必需的操作,然后再对结果进行取幂.这允许您的值临时离开浮动域空间,同时仍然准确地计算浮动域内的最终答案.

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 + 1))
...
math.exp(result)
Run Code Online (Sandbox Code Playgroud)

这将保留在日志域中,直到最后,因此在您遇到溢出问题之前,您的数字可能会变得非常非常大.


xyl*_*n97 4

尝试使用十进制库。它声称支持任意精度。
from decimal import Decimal

另外,您不需要使用math.pow. pow是内置的。