Python中的OverflowError: long int too large to convert to float错误

44

我尝试在Python中计算泊松分布,代码如下:

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

idx的取值范围为0。

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

我尝试将depart转换为float,但没有结果。


阶乘增长非常快,而且速度非常快。 - Hunter McMillen
1
当您遇到此错误时,idx的值是多少? - Pyrce
当你想计算阶乘时,可以计算它的对数。 - AturSams
5个回答

43

阶乘增长速度非常快

>>> math.factorial(170)
7257415615307998967396728211129263114716991681296451376543577798900561843401706157852350749242617459511490991237838520776666022565442753025328900773207510902400430280058295603966612599658257104398558294257568966313439612262571094946806711205568880457193340212661452800000000000000000000000000000000000000000L

注意这里的L,即使对于阶乘为170的情况,其结果仍可转换为浮点数:
>>> float(math.factorial(170))
7.257415615307999e+306

但是下一个阶乘太大了:

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

你可以使用decimal模块,虽然计算速度较慢,但是Decimal()类可以处理这么大的阶乘:

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

您需要始终使用 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)

Python中的大数类叫什么?因为170!远超过了64位整数的限制。我猜类型被强制转换成了那个吧?如果是这样,为什么还要在末尾添加L呢? - Hunter McMillen
3
Python的长整型只受限于操作系统内存分配。在我的情况下,L代表我们超出了该平台的最大C整数大小(64位),以表示正在使用长整型;转换是自动进行的。参见http://docs.python.org/2/library/stdtypes.html#numeric-types-int-float-long-complex。 - Martijn Pieters
啊,我明白了。大多数其他编程语言都有BigInteger或类似的东西。谢谢。 - Hunter McMillen

7
idx变大时,math.pow和/或math.factorial 会变得非常大,难以转换为浮点值(在我的64位机器上idx = 1000会触发错误)。你应该不使用math.pow函数,因为它比内置的**运算符早溢出,因为它尝试通过提前进行浮点转换来保持更高的精度。此外,您还可以将每个函数调用包装在Decimal对象中,以获得更高的精度。
处理非常大的数字的另一种方法是在对数刻度下工作。获取每个值的对数(或计算每个值的对数版本),并在获取结果的指数之前执行所有所需操作。这样,即使值暂时离开浮点域空间,仍然可以准确地计算最终答案,该答案位于浮点域内。
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)

这个值一直保持在日志域,直到最后,因此您的数字可以变得非常非常大,然后再出现溢出问题。


1
我认为 3 ** idx => math.log(3) * math.log(idx) 应该改为 3 ** idx => math.log(3) * idx - Shubham Saini

4

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

此外,您不需要使用math.pow。pow已是内置函数。


大家好,我尝试使用decimal或scipy,但是出现了以下错误:ImportError: No module named scipy.stats对于decimal也是同样的错误。 - user2312186
你正在运行哪个版本?decimal 库应该是标准的。也许你已经删除了它。重新安装 Python 就可以解决这个问题。至于 Scipy,它是一个第三方包,所以你需要从 scipy.org 下载它。 - xylon97
我要像这样使用泊松分布:depart = depart + Poisson(3),以便通过泊松分布选择间隔时间。但是它不起作用。 - user2312186

2

+1 对于 scipy.stats,但是 scipy 提供的阶乘函数在大参数下仍然会返回 inf - DSM
谢谢。我将生成泊松数作为网络中生成数据包时间的方法。如何使用此函数连续生成泊松数? - user2312186

0
如果您在使用非常大的数字进行除法时遇到此错误,请改用地板除法运算符(//)而不是//始终返回一个float,无论商是否为整数,但是//将始终返回一个int,因为它忽略任何余数。
当您只需要最接近的整数或者知道不会有余数时,地板除法很有效。
例如:
n = 5479174226627386185132548618631889901184058567721039026663537776859958572142823922154018004124214331284656070023110969954188349772902119804704702598117413535893235324950786546151906304553125886840777572957470085282511148870434624033780058878942475280220905204940912590689793763351716319910433886468914385951305420981218341758360474092776301397873143398400716102216234362319599979129849103060426402698870872632043715074191472826989513693244855131547410762874345810755472991691149113189232066769661520546071424890254793363936991126744220856839621014660137423821784120362098968560498064575399109509809144075148032776900847515603985610957107880554355044275212955190073519527570422912054125513731742317779855206190407418289517246109264745652852110081421227227070961742013273408514723195685741381697286381613758857699193539587512284537797999746347217299424379359513750952221691770954364716137930556670199833832758082670990435174217159016818867385870452581971005123842835195274660590963683055276508447399891075634175690730834545095637653926683291205950640671169613344094321183481673015248807254721861961606825265236717120630995029306863300152797740979622723077992597531418730154060586722026762649940060327662106126471869300626956821351541276596745066988430327015357076633723108282682951496900104227774031265608955533139148284989331915052933624499658651051440828202238489960326767828269045239036246524560280599359429362948869990238325225414863546810033093049656312737083470849175724716280988160656752494507880308537719866213986281428744395701992495890900685006572556038647427947211000473774809669487947261242971504873560862774351759068398609198938063648190986411623475678601785762035198084851677024720418537109078696439281976199801473556400242587983954277326038907443266131383984144369164421859162116568291430549701757135817698503903004323670868472322098027272184621482168087031650528289698350186047041813000034365448608048428773660686833199312751498967864183755218605831200984734033178462911134687785324823763323028015552729641117736966587793077203826296036041919194725026292750532442085716784596992382527663553269382473454979408093249648685286746030229491081455014614036595064858640568694698486979304728018771546672574024918565616067368338166156732338857331627951808169957419646902230036338741999953636036848632388844148127317892455668907319296843822473855127548875966047711681567056047142200887652753813947766711904166025820768269034575968052119510503904027778183601434729384390496315574344178298921662230866717650218116213036528198477594125535378602905735898504877520174927689474709976093921901862335223731814101741854177482601528306067859536805771591038922076905431603327032115233190666894167725361120047719134862842475859620392485715336420653304556079280724582370679687097844646877141209557539992623586632733333757970772758010549948610992979279029728363939092740579103618926669219471007734885307035386951609417262492554868268269616601555317177098129073353194374818770380635286890143608518924421556937379652833811709922933535682467614307592250619010586908268258080894148787717354387660022563306126433196292155158692150378675047252139601642814517370404428943577553004710999041554686557359791855943269834124640464693626652005988300338967392066239532981003255609078688925846590550467734155623629681262423331018717094741382157740779203008752310807956601087650996558858762789654321362720766176441413026718299435000087843048352098779842582683343460060362948117211949633698490613691410568825978953300376848779528540637469856488967807293836747161816004817653656673962008997810605012877379655141001116834025783685768201503435029018375437319930124960810208705813192640556535800129029066957647413650553915827395477280121732521449721923559779963923510646372389370353922598568377127428196541696965429553407721148989373822271488


divisor = 2

if n % divisor == 0:
    # We know the number is evenly divisible by the divisor, so we can use // without losing any possible remainder
    quotient = n // divisor  # This will work just fine

# This line will give an error since / always returns a float
quotient = n / divisor
# OverflowError: integer division result too large for a float

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接