Python: limit on the accuracy of float

653 Views Asked by At

The code gives an error because the value of "var" is very close to zero, less than 1e-80. I tried to fix this error using "Import decimal *", but it didn't really work. Is there a way to tell Python to round a number to zero when float number is very close to zero, i.e. < 1e-50? Or any other way to fix this issue?
Thank you
CODE:

import math
H=6.6260755e-27
K=1.3807e-16
C=2.9979E+10
T=100.0
x=3.07175e-05

cst=2.0*H*H*(C**3.0)/(K*T*T*(x**6.0))
a=H*C/(K*T*x)
var=cst*math.exp(a)/((math.exp(a)-1.0)**2.0)
print var

OUTPUT:

Traceback (most recent call last):
  File "test.py", line 11, in <module>
  var=cst*math.exp(a)/((math.exp(a)-1.0)**2.0)
OverflowError: (34, 'Numerical result out of range')

To Kevin: The code was edited with following lines:

from decimal import *
getcontext().prec = 7
cst=Decimal(2.0*H*H*(C**3.0)/(K*T*T*(x**6.0)))
a=Decimal(H*C/(K*T*x))
2

There are 2 best solutions below

0
chepner On

The problem is that (math.exp(a)-1.0)**2.0 is too large to hold as an intermediate result.

>>> (math.exp(a) - 1.0)**2.0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')

However, for the value of a you are using,

>>> math.exp(a)/(math.exp(a)-1.0) == 1.0
True

so you can essentially cancel that part of the fraction, leaving

var = cst/(math.exp(a)-1.0)

which evaluates nicely to

>>> cst/(math.exp(a)-1.0)
7.932672271698049e-186

If you aren't comfortable rewriting the formula to that extent, use the associativity of the operations to avoid the large intermediate value. The resulting product is the same.

>>> cst/(math.exp(a)-1.0)*math.exp(a)/(math.exp(a)-1.0)
7.932672271698049e-186
0
Curiosity On

I solved this issue but that will work only for this particular problem, not in general. The main issue is the nature of this function:

math.exp(a)/(math.exp(a)-1.0)**2.0

which decays very rapidly. Problem can be easily solved restricting the value of "a" (which won't make any significant change in calculation). i.e.

if a>200:
    var=0.0
else:
    var=cst*math.exp(a)/((math.exp(a)-1.0)**2.0)