Solución:
Su resultado es incorrecto porque el decimal también tiene precisión (decimal es matemática de punto fijo), por lo que también tiene un problema de desbordamiento aquí:
Decimal('.01')**Decimal('1e6')
Decimal (‘0E-1000026’)
Pero:
getcontext().prec = 1000000000 # sets precision to 1000000000
Decimal('.01')**Decimal('1e6')
Decimal (‘1E-2000000’)
Puede solucionar su problema configurando manualmente la precisión como en el ejemplo anterior o calcular manualmente las potencias, por ejemplo:
Decimal('.01')**Decimal('1e6')
se puede convertir a
Decimal('1e-2') ** Decimal('1e6')
y luego a
1 ** ((-2) ** 1e6) = 1 ** (-2000000)
Documentación del módulo decimal
¿Por qué no usar logaritmos?
Quieres calcular:
RESULT = x1 * x2 * x3 * x4 ... * xn
Represente eso como:
ln(RESULT) = ln(x1) + ln(x2) + ln(x3) + ln(x4) ... + ln(xn)
Los números positivos muy pequeños se almacenan muy bien en flotantes si almacena su logaritmo natural:
ln(0.000001) ≈ -13.81551
En lugar de almacenar los números en sí, almacene el registro de los valores.
Suponga que agrega ln(0.0000011)
a sí mismo 10^6
veces. Obtienes aproximadamente -13815510.558
. Se pierde menos precisión en eso como float
que 0.000001^(10^6)
Cualquiera que sea el número que obtenga al final, sabe que su resultado es solo el número e
elevado a ese poder. Por ejemplo, RESULT = e^-13815510.558
Puede utilizar el siguiente código:
import math
class TinyNum:
def __init__(self, other=None, *, pow=None):
"""
x = TinyNum(0.0000912922)
x = TinyNum("0.12345") # strings are okay too
x = TinyNum(pow = -110) # e^-110
y = TinyNum(x) # copy constructor
"""
if other:
if isinstance(other, type(self)):
self._power = other._power
else:
self._power = math.log(float(str(other)))
else: # other == None
self._power = float(str(pow))
def __str__(self):
return "e^"+str(self._power)
def __mul__(lhs, rhs):
rhs = type(lhs)(rhs)
return type(lhs)(pow=lhs._power + rhs._power)
def __rmul__(rhs, lhs):
lhs = type(rhs)(lhs)
return type(rhs)(pow=lhs._power + rhs._power)
def __imul__(total, margin):
total._power = total._power + type(total)(margin)._power
lyst = [
0.00841369,
0.004766949,
0.003188046,
0.002140916,
0.004780032
]
sneaky_lyst = map(TinyNum, lyst)
print(math.prod(sneaky_lyst))
El mensaje impreso en la consola es:
e^-27.36212057035477