Para mantener la precisión mientras agrega dobles, debe usar Kahan Summation , este es el software equivalente a tener un registro de acarreo.
Esto está bien para la mayoría de los valores, pero si obtiene un desbordamiento, entonces está alcanzando los límites de la precisión doble IEEE 754, que sería aproximadamente . En este punto necesitas una nueva representación. Puede detectar un desbordamiento en el momento de la adición y también detectar exponentes demasiado grandes para evaluarlos . En este punto, puede modificar la interpretación de un doble cambiando el exponente y haciendo un seguimiento de este cambio.mi709.783doubleMax - sumSoFar < valueToAdd
exponent > 709.783
En su mayor parte, esto es similar a su enfoque de compensación de exponente, pero esta versión se mantiene en la base 2 y no requiere una búsqueda inicial para encontrar el exponente más grande. Por lo tanto, .v a l u e × 2s h i f t
#!/usr/bin/env python
from math import exp, log, ceil
doubleMAX = (1.0 + (1.0 - (2 ** -52))) * (2 ** (2 ** 10 - 1))
def KahanSumExp(expvalues):
expvalues.sort() # gives precision improvement in certain cases
shift = 0
esum = 0.0
carry = 0.0
for exponent in expvalues:
if exponent - shift * log(2) > 709.783:
n = ceil((exponent - shift * log(2) - 709.783)/log(2))
shift += n
carry /= 2*n
esum /= 2*n
elif exponent - shift * log(2) < -708.396:
n = floor((exponent - shift * log(2) - -708.396)/log(2))
shift += n
carry *= 2*n
esum *= 2*n
exponent -= shift * log(2)
value = exp(exponent) - carry
if doubleMAX - esum < value:
shift += 1
esum /= 2
value /= 2
tmp = esum + value
carry = (tmp - esum) - value
esum = tmp
return esum, shift
values = [10, 37, 34, 0.1, 0.0004, 34, 37.1, 37.2, 36.9, 709, 710, 711]
value, shift = KahanSumExp(values)
print "{0} x 2^{1}".format(value, shift)