I need to multiply about 1e6
numbers that are of the order of 0.01
. The expected result is of order 1e-100000000
. Obviously the typical floating-point arithmetic cannot handle this.
Doing some research on the web I found the decimal library which seems to fix this problem. However it appears to have limitations that make it useless for my needs:
>>> Decimal('.01')**Decimal('1e5') # Seems to handle this
Decimal('1E-200000')
>>> Decimal('.01')**Decimal('1e5')*Decimal('1E200000') # Yeah! It works!
Decimal('1')
>>> Decimal('.01')**Decimal('1e6') # This result is strange...
Decimal('0E-1000026')
>>> Decimal('.01')**Decimal('1e6')*Decimal('0E1000026') # Wrong result
Decimal('0')
Does anyone know any solution to this?
Your result is incorrect because decimal has precision too (decimal is fixed point math), so you get underflow issue here too:
Decimal('.01')**Decimal('1e6')
Decimal('0E-1000026')
But:
getcontext().prec = 1000000000 # sets precision to 1000000000
Decimal('.01')**Decimal('1e6')
Decimal('1E-2000000')
You can fix your issue by manualy setting precision as in example above or manually calculate powers, for example:
Decimal('.01')**Decimal('1e6')
can be converted to
Decimal('1e-2') ** Decimal('1e6')
and later to
1 ** ((-2) ** 1e6) = 1 ** (-2000000)