[英]OverflowError: (34, 'Result too large')
我收到溢出错误(溢出错误:(34,'结果太大')
我想将 pi 计算为 100 位小数,这是我的代码:
def pi():
pi = 0
for k in range(350):
pi += (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
return pi
print(pi())
Python 浮点数既不是任意精度也不是无限大小。 当 k = 349 时, 16.**k
太大了 - 几乎是 2^1400。 幸运的是, decimal
库允许任意精度并且可以处理大小:
import decimal
decimal.getcontext().prec = 100
def pi():
pi = decimal.Decimal(0)
for k in range(350):
pi += (decimal.Decimal(4)/(decimal.Decimal(8)*decimal.Decimal(k+1))...)
您达到了平台float
支持的限制,可能是在k = 256
:
>>> k = 256
>>> (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')
>>> k = 255
>>> (4./(8.*k+1.) - 2./(8.*k+4.) - 1./(8.*k+5.) - 1./(8.*k+6.)) / 16.**k
3.19870064997e-313
有关确切的限制,请参阅sys.float_info
,但您不太可能遇到在任何情况下都会为您提供 100 位有效数字的当前 CPU 和操作系统组合; 我的 64 位 OS X MacBook Pro 只支持 15。
使用decimal
模块超越您的硬件限制。
from decimal import Decimal, localcontext
def pi():
with localcontext() as ctx:
ctx.prec = 100 # 100 digits precision
pi = Decimal(0)
for k in range(350):
pi += (Decimal(4)/(Decimal(8)*k+1) - Decimal(2)/(Decimal(8)*k+4) - Decimal(1)/(Decimal(8)*k+5) - Decimal(1)/(Decimal(8)*k+6)) / Decimal(16)**k
return pi
16.**256 太大,无法存储在双精度浮点数中。 我建议你少运行你的循环,比如 range(250),因为更大的 k 值无论如何都不会影响前一百位数字。
您可能会尝试的另一件事是乘以 16.* (-k) 而不是除以 16. *k。 对于大 k,此数字将四舍五入为零,因此不会给您带来运行时错误。
我建议你使用 numpy.power 而不是 **,它可以更好地处理溢出。 例如,在您的代码中 numpy.power(16.,256) 将评估为 inf,并且将有限数除以 inf 得到零,这避免了运行时错误,就像上一段中建议的方法一样。
我使用python3.6 AMD64,我也遇到这个问题,这是因为python内置的float
是双精度浮点数,它是64位,在大多数编程任务中,64位就足够了,但在一些额外的任务中,它不是足够(如科学计算,大数据计算)
这是使用十进制库解决此问题的python 解决方案。 此代码计算 pi 的一千位数字。
import decimal
def pi( prec = 10 ** 3 ):
decimal.getcontext().prec = prec
b = decimal.Decimal(1)
pi = 0
for k in range(prec):
pi += ( b*4/(8*k+1) - b*2/(8*k+4) - b*1/(8*k+5) - b*1/(8*k+6)) / 16**k
return pi
print(pi())
这是仅使用内置任意大小整数的解决方案。 它的工作效率更高,并允许您计算 pi 的一万位数字。
def pi( prec = 10 ** 4 ):
b = 10 ** prec
pi = 0
for k in range(prec):
pi += ( b*4//(8*k+1) - b*2//(8*k+4) - b*1//(8*k+5) - b*1//(8*k+6)) // 16**k
return pi
print(pi())
通过开始这段代码,你可以向你的朋友吹嘘你已经把一万当作圆周率了:)。
如果您需要几乎无限的精度,请使用十进制。
在极少数情况下,如果您正在执行n ** 2
或类似的操作。 您可以通过将其转换为n * n
来避免错误而不捕获它,因此根据您如何解决这个问题,它可能是一个可靠的解决方案。 您的数字将被称为inf
而不是抛出错误, **
执行幂函数并且它是抛出错误的那个。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.