두 배를 더하는 동안 정밀도를 유지하려면 Kahan Summation 을 사용해야 합니다. 이것은 캐리 레지스터를 갖는 것과 동등한 소프트웨어입니다.
이것은 대부분의 값에는 문제가 없지만 오버플로가 발생하면 IEEE 754 배정 밀도 한계에 도달합니다 . 약 입니다. 이 시점에서 새로운 표현이 필요합니다. 추가시 오버플로를 감지하고 로 평가할 지수를 크게 감지 할 수도 있습니다 . 이 시점에서 지수를 이동하고이 이동을 추적하여 double의 해석을 수정할 수 있습니다.e709.783doubleMax - sumSoFar < valueToAdd
exponent > 709.783
이것은 대부분 지수 오프셋 접근 방식과 유사하지만이 버전은 기본 2에 유지되며 가장 큰 지수를 찾기 위해 초기 검색이 필요하지 않습니다. 따라서 입니다.value×2shift
#!/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)