Мы знаем log_add, но как сделать log_subtract?
Умножение двух чисел в лог-пространстве означает их добавление:
log_multiply(x, y) = log( exp(x) * exp(y) )
= x + y
Добавление двух чисел в лог-пространстве означает, что вы выполняете специальную операцию добавления журнала:
log_add(x, y) = log( exp(x) + exp(y) )
который реализован в следующем коде, таким образом, что нам не требуется брать две экспоненты (и потерять скорость и точность выполнения):
double log_add(double x, double y) {
if(x == neginf)
return y;
if(y == neginf)
return x;
return max(x, y) + log1p(exp( -fabs(x - y) ));
}
(Здесь - еще один.)
Но вот вопрос:
Есть ли уловка для его вычитания?
log_subtract(x, y) = log( exp(x) - exp(y) )
без необходимости брать экспоненты и потерять точность?
double log_subtract(double x, double y) {
// ?
}
Ответы
Ответ 1
Как насчет
double log_subtract(double x, double y) {
if(x <= y)
// error!! computing the log of a negative number
if(y == neginf)
return x;
return x + log1p(-exp(y-x));
}
Это просто основано на некоторой быстрой математике, которую я сделал...
Ответ 2
Библиотека выполняет функции exp и log, теряя точность для экстремальных значений.
log1p получает вас на полпути, но вам нужна функция, которая обрабатывает ошибку как для журнала, так и для частей exp.
Смотрите эту статью: http://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf
Название "Точный журнал вычислений (1 - exp (- | a |))".
В статье обсуждается, как безразлично объединить различные алгоритмы для создания хороших границ ошибок для большего диапазона входов.