Является ли реализация функции exp () с плавающей точкой эквивалентной усеченному разложению в ряд Тейлора?

Является ли реализация функции exp () с плавающей запятой в cmath эквивалентной усеченному разложению в ряд Тейлора очень высокого порядка? Один из возможных источников ошибки, о котором мы должны помнить, это конечность числа битов, представляющих ответ.

2

Решение

Является ли реализация функции exp () с плавающей запятой в cmath эквивалентной усеченному разложению в ряд Тейлора очень высокого порядка?

Эквивалент? Да. Это потому, что любая достойная реализация exp() имеет ошибку половины ULP (единицы наименьшей точности) или около того. Игнорируя проблемы с арифметикой конечной точности, всегда можно построить усеченный ряд Тейлора, который делает то же самое.

Тем не менее, нет достойной реализации exp() будет использовать расширение Тейлора. Это будет очень-очень медленно и не достигнет желаемой точности. Это было бы совершенно глупой реализацией. Намного лучше использовать тот факт, что между двумяИкс и еИкс и тот факт, что 2Икс довольно легко вычислить, учитывая почти универсальную степень 2 представления чисел с плавающей запятой.

5

Другие решения

Это зависит от реализации компилятора, времени выполнения C и процессора. Однако тот, кто вычисляет показатель, вряд ли будет использовать разложение Тейлора, поскольку существуют лучшие методы.

Согласно glibc, он может использовать свою собственную реализацию, которая говорит об этом в комментарии (из sysdeps / ieee754 / dbl-64 / e_exp.c):

/* An ultimate exp routine. Given an IEEE double machine number x          */
/* it computes the correctly rounded (to nearest) value of e^x             */

Или он может использовать аппаратно поддерживаемые инструкции процессора для вычислений с плавающей запятой, как с x86 FPU. В обоих случаях вы, вероятно, получите правильно округленное значение с полной точностью.

1

Просто пример того, как вы можете рассчитать exp (x):

Если x довольно большой, то результат + inf. Если х довольно мало, то результат равен 0.

Пусть k = round (x / ln 2). Тогда exp (x) = 2 ^ k * exp (x — k ln 2). 2 ^ k очень легко вычислить. Небольшой проблемой является вычисление x — k ln 2 без какой-либо ошибки округления. Это довольно просто: пусть L1 = ln 2 округлено до 35 бит, а L2 = ln 2 — L1. k — малое целое число, поэтому k * L1 не имеет ошибки округления и не имеет x — k * L1; затем вычитаем k * L2, которое мало и поэтому имеет небольшую погрешность округления.

Чтобы сделать это быстрее (без деления), мы вычисляем k = round (x * (1 / ln 2)). И мы проверяем, близок ли x к нулю, поэтому весь расчет не нужен. В любом случае, теперь мы вычисляем exp (x), где результат находится между sqrt (1/2) и sqrt (2).

Вы можете вычислить exp (x), используя полином Тейлора. Вместо этого вы, вероятно, использовали бы полином Чебычева, минимизирующий ошибку отсечки с гораздо меньшей степенью. С некоторой осторожностью вы можете найти многочлен с ошибкой отсечки, существенно меньшей, чем младший бит результата.

1

Это зависит от того, какую реализацию библиотеки C вы используете. В очень популярном glibc это не так.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector