Аппроксимация функций рядами Маклаурина - PullRequest
1 голос
/ 17 марта 2011

Мне нужно прибл. (1-x) ^ 0,25 с заданной точностью (например, 0,0001). Я использую расширение , найденное в Википедии для (1 + x) ^ 0.25. Мне нужно прекратить приближение, когда текущее выражение меньше точности.

long double s(long double x, long double d) {
    long double w = 1;
    long double n = 1; // nth expression in series
    long double tmp = 1;

    // sum while last expression is greater than accuracy
    while (fabsl(tmp) >= d) {
        tmp *= (1.25 / n - 1) * (-x); // the next expression
        w += tmp; // is added to approximation
        n++; 
    } 

    return w;
}

Не возражаю против длинных двойных n. : P Это хорошо работает, когда я проверяю не значение текущего выражения, а когда я вычисляю 1000 или более выражений. Область функции <-1; 1>, а s () хорошо вычисляет аппроксимацию для x в <-1; ~ 0,6>. Чем больше аргумент, тем больше погрешность расчета. С 0,6 это превышает точность.

Я не уверен, что проблема достаточно ясна, потому что я плохо знаю английский математический язык. Дело в том, что с условием while, и почему функция s () некорректно аппроксимируется.

EDIT: Проблема в основном решена. Когда x> 0, я должен вычесть абсолютное значение последовательных выражений из 1.

if (x<0)
   w += tmp;
else
   w -= fabsl(tmp);

После этого точность значительно возрастает (лиса х> 0, конечно). Избыточная ошибка происходит из-за длинной двойной неточности. Это все. В любом случае, спасибо вам, ребята.

Ответы [ 2 ]

1 голос
/ 17 марта 2011

Ваша проблема в том, что хотя итерационная часть вашего алгоритма в порядке, завершение не то, что вы думаете.

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

Я полагаю, вы предполагаете, что когда tmp становится меньше, чем ваш желаемый допуск, тогда ошибка в w также меньше этого допуска.

Однако это не так. Ошибка на каждой итерации представляет собой бесконечную сумму оставшихся членов. Это сумма бесконечного числа терминов, которые вы выбрасываете. Первое из них, значение tmp в точке завершения, может быть меньше, чем ваша терпимость, но сумма их всех может быть больше, чем ваша терпимость.

Вам сходит с рук, когда (-x) отрицателен, потому что знакопеременный знак tmp работает в вашу пользу. И когда (-x) положительно, вам это сходит с рук, когда x близко к нулю.

Однако я не уверен, что есть простой способ придумать простые критерии остановки общего назначения. Вы должны быть в состоянии поставить некоторые ограничения на условия, которые вы выбрасываете. Теперь это становится математической проблемой, а не проблемой программирования.

1 голос
/ 17 марта 2011

Попробуйте нарисовать график функции

abs((1.0+x)<sup>alpha</sup> - binomial_formula(alpha,x,tolerance))
даже в близком диапазоне x, например [-0.5; 0.5], вы получите что-то вроде: enter image description here

Это означает, что ваша реализация биномиального расширения нестабильна. Поскольку x становится все дальше и дальше от нуля, ряды должны включать в себя все больше и больше терминов для заданной точности. Но выполнение этого в текущей реализации расширения вызывает катастрофическое аннулирование (некоторый механизм накопления ошибок с плавающей запятой). Попробуйте прочитать мою приведенную ссылку о том, как разработать численно устойчивый алгоритм.

Кстати, спасибо за действительно интересную проблему!

...