Saltar al contenido

Manejo de números muy muy pequeños en Python

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
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *