Why do I get "OverflowError: (34, 'Result too large')" or "OverflowError: (34, 'Numerical result out of range')" from floating-point exponentiation?
Question:
I tried to use this code to calculate pi to many decimal places:
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())
Why do I get an error that says OverflowError: (34, 'Result too large')
?
Answers:
You reached the limits of your platform’s float
support, probably after 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
See sys.float_info
for the exact limitations, but you are unlikely to run into a current CPU and OS combination that’ll give you 100 significant digits in any case; my MacBook Pro with 64-bit OS X will only support 15.
Use the decimal
module to go beyond your hardware limitations.
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
Python floats are neither arbitary precision nor of unlimited size. When k = 349, 16.**k
is much too large – that’s almost 2^1400. Fortunately, the decimal
library allows arbitrary precision and can handle the size:
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))...)
16.**256 is too large to be stored in double precision float. I suggest that you run your cycle for less, like range(250), because larger k values will not contribute to the first hundred digits anyway.
Another thing you might try is to multiply by 16.*(-k) instead of dividing by 16.*k. This number will be rounded to zero for large k, therefore will not give you runtime errors.
I suggest that you use numpy.power instead of **, it handles overflows better. For example, in your code numpy.power(16.,256) would evaluate to inf, and dividing a finite number by inf gives zero, which avoids runtime errors just like the method suggested in the previous paragraph.
I use python3.6 AMD64,I also meet this problem,this is because python built-in float
is double-precision-float,it’s 64 bit,in most progamming task,64 bit is enough,but in some extra task,it’s not enough(like scitific computing,big data compute)
This is a python solution to this problem using the decimal library. This code counts one thousand digits of 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())
This is a solution using only the built-in any size integers. It works much more efficiently and allows you to count ten thousand digits of 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())
By starting this code, you can brag to your friends that you have counted ten thousand as pi :).
Use decimal if you need nearly infinite precision.
In some rare cases if you’re doing n ** 2
or something like that. You can avoid the error without catching it by just converting that to n * n
so depending on how you get to your this problem it might be a solid fix for this. Your numbers will be called inf
rather than throwing an error, the **
does the power function and it is the one throwing the error.
I tried to use this code to calculate pi to many decimal places:
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())
Why do I get an error that says OverflowError: (34, 'Result too large')
?
You reached the limits of your platform’s float
support, probably after 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
See sys.float_info
for the exact limitations, but you are unlikely to run into a current CPU and OS combination that’ll give you 100 significant digits in any case; my MacBook Pro with 64-bit OS X will only support 15.
Use the decimal
module to go beyond your hardware limitations.
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
Python floats are neither arbitary precision nor of unlimited size. When k = 349, 16.**k
is much too large – that’s almost 2^1400. Fortunately, the decimal
library allows arbitrary precision and can handle the size:
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))...)
16.**256 is too large to be stored in double precision float. I suggest that you run your cycle for less, like range(250), because larger k values will not contribute to the first hundred digits anyway.
Another thing you might try is to multiply by 16.*(-k) instead of dividing by 16.*k. This number will be rounded to zero for large k, therefore will not give you runtime errors.
I suggest that you use numpy.power instead of **, it handles overflows better. For example, in your code numpy.power(16.,256) would evaluate to inf, and dividing a finite number by inf gives zero, which avoids runtime errors just like the method suggested in the previous paragraph.
I use python3.6 AMD64,I also meet this problem,this is because python built-in float
is double-precision-float,it’s 64 bit,in most progamming task,64 bit is enough,but in some extra task,it’s not enough(like scitific computing,big data compute)
This is a python solution to this problem using the decimal library. This code counts one thousand digits of 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())
This is a solution using only the built-in any size integers. It works much more efficiently and allows you to count ten thousand digits of 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())
By starting this code, you can brag to your friends that you have counted ten thousand as pi :).
Use decimal if you need nearly infinite precision.
In some rare cases if you’re doing n ** 2
or something like that. You can avoid the error without catching it by just converting that to n * n
so depending on how you get to your this problem it might be a solid fix for this. Your numbers will be called inf
rather than throwing an error, the **
does the power function and it is the one throwing the error.