부동 소수점의리스트를 구하고 싶다면, 로그를 추가하고 단지 합계 대신에 합계를 취함으로써 잃어버린 최악의 경우/평균의 경우의 정밀도는 얼마입니까? 그들을 곱하십시오. 이것이 실제로 더 정확한 경우가 있습니까?로그를 받고 추가 대 곱하기
답변
a
및 b
이 부동 소수점 숫자 인 경우 a*b
은 1/2 ulp의 상대 오차 내에서 계산됩니다.
N
double
의 체인 승산 후의 상대 오차에 결합 원유 따라서 배 않음 오프를 초래하게는 (1 - (ε)/2) EXP 관한 -N (엡실론 N
/2). 나는 평균적인 경우에 엡실론 sqrt (N
)의 편차를 기대할 수 있다고 생각합니다. (첫 번째 순서는 N 엡실론에 관한 것입니다.)
이 전략에서는 지수 오버 플로우와 언더 플로우가 발생할 가능성이 더 높습니다. subnormals의 반올림으로 인해 무한, 제로 및 NaN뿐 아니라 부정확 한 값을 얻을 가능성이 큽니다.
다른 접근법은 그 의미에서보다 견고하지만, 직접적인 접근으로 인해 오버플로 또는 언더 플로우가 발생하지 않는 경우 훨씬 느리고 오류가 더 심합니다. 다음은 N이 2 자리 크기보다 작은 경우의 표준 double에 대한 매우 조잡한 분석입니다. :
언제나 유한 부동 소수점 로그를 가져 와서 유한 부동 소수점 수이므로 우리는 거기 멋지다. N
부동 소수점 수를 직접 추가하여 N
엡실론 최악의 "상대"오류 및 sqrt (N) 엡실론 예상 "상대"오류를 얻거나 Kahan summation을 사용하여 최악의 "엡손"상대 오류를 얻을 수 있습니다. 깜짝 따옴표는 "상대적인"주위에 있습니다. 왜냐하면 오류는 합계하는 것의 절대 값의 합에 상대적이기 때문입니다.
절대 값이 710을 넘는 대수가없는 유한수 double
에 주목하십시오. 즉, Kahan 합계를 사용하여 계산 된 우리 로그의 합은 절대 오차가 최대 2130 N 엡실론입니다. 우리가 우리의 sum of logarithm을 exponentiate 할 때, 우리는 정답에서 최대 exp (2130 N ε)의 인자로 무언가를 얻습니다. 로그 - 합 - 특급 접근
병리학 예 : 내 플랫폼에
int main() {
double foo[] = {0x1.000000000018cp1023, 0x1.0000000000072p-1023};
double prod = 1;
double sumlogs = 0;
for (int i = 0; i < sizeof(foo)/sizeof(*foo); i++) {
prod *= foo[i];
sumlogs += log(foo[i]);
}
printf("%a %a\n", foo[0], foo[1]);
printf("%a %a %a\n", prod, exp(sumlogs), prod - exp(sumlogs));
}
, 나는 0x1.fep-44의 차이를 얻는다. 나는 더 나쁜 예가 있다고 확신한다.
님께 고마워했습니다. log-sum-exp를 분석 한 게시 된 기사가 있습니까? –
내 "로그"태그를 "로깅"으로 계속 변경합니다. 난 그것에 대해 meta-stackoverflow – dspyz
에 대해 물어 볼게 당신은 대신 "로그"를 사용할 수 있습니다. – Jonas
설명해 주신 덕분에 – dspyz