Часто для вычисления некоторой функции используется её разложение в бесконечный ряд. Например, функцию можно представить в виде ряда Маклорена:
Ряды можно суммировать, учитывая количество слагаемых (например, найти сумму первых n слагаемых) или, если ряд сходящийся, то вычислять сумму с заданной точностью.
Правило. Говорят, что сумма сходящегося ряда подсчитана с заданной точностью ε, т.е. выполняется неравенство если где
— сумма первых n слагаемых,
— сумма первых n+1 слагаемых,
— n+1 слагаемое.
Исходя из этого правила, несложно понять, что для вычисления суммы ряда с заданной точностью необходимо продолжать процесс суммирования до тех пор, пока очередные слагаемые больше по модулю искомой точности. Если же очередное слагаемое оказалось меньше (или равно) искомой точности, то процесс суммирования можно прекратить.
Вычисление слагаемых суммируемого ряда далеко не всегда является тривиальной задачей. В зависимости от вида слагаемых ряда выбирается и метод их вычисления. Условно все ряды можно разбить на три группы. Дадим их характеристику и рассмотрим, каким образом лучше суммировать эти ряды.
Первая группа — ряды, в которых каждое слагаемое, кроме, может быть, одного или нескольких первых, полностью выражается через предыдущее слагаемое. Обычно это ряды, в которых для каждого слагаемого требуется вычислять факториалы и возводить некий аргумент в степени высших порядков.
Пример 1. Найти сумму ряда с заданной точностью ε:
Как вести суммирование такого ряда? Прежде всего, необходимо вывести формулу для вычисления очередного слагаемого. Введём обозначения для очередных слагаемых:
и так далее. Очевидно, что можно выразить:
В общем виде можно записать:
Эта формула справедлива для всех слагаемых, кроме Следовательно, все слагаемые, кроме нулевого, вычисляем по этой формуле в цикле и добавляем к ранее найденной сумме. Процесс суммирования продолжаем до тех пор, пока очередное слагаемое не станет меньше или равно требуемой точности.
Возможная реализация программы:
#include <iostream>
using namespace std;
#include <cmath>
int main()
{
double x, p, s, i, eps = 1.0e-4;
cout << "x=";
cin >> x;
for(i = 1, s = 1, p = 1; fabs(p) > eps; i++)
{
p = - p * x / i;
s += p;
}
cout << "s=" << s << endl;
return 0;
}
Вторая группа — это ряды, в которых нельзя полностью выразить очередное слагаемое через предыдущее, но можно составные части этого слагаемого выразить через соответствующие части предыдущего слагаемого.
Пример 2. Найти сумму ряда с заданной точностью ε:
Этот ряд очень похож на ряд из примера 1, но добавление одного множителя в знаменателе каждого слагаемого заметно усложняет работу. Выход напрашивается сам собой: представим каждое слагаемое в виде дроби
где
Возможная реализация программы:
#include <iostream>
using namespace std;
#include <cmath>
int main()
{
double a, x, p, s, i, eps = 1.0e-4;
cout << "x=";
cin >> x;
for(i = 1, a = 1, s = 1, p = 1; fabs(p) > eps; i++)
{
a = - a * x / i;
p = a / i;
s += p;
}
cout << "s=" << s << endl;
return 0;
}
Третья группа — это ряды, в которых каждое слагаемое зависит только от его номера. Обычно в таких рядах нет факториалов и степеней высших порядков.
Пример 3. Найти сумму первых n слагаемых:
Найти формулу для вычисления очередного слагаемого несложно:
Обратите внимание на следующий момент. В предыдущих двух примерах изменение знака слагаемых мы очень просто реализовали или в формулах вычисления очередного слагаемого
p = - p * x / i; // пример 1
или части слагаемого
a = - a * x / i; // пример 2
Здесь же (пример 3) пришлось завести специальную переменную z для изменения знака слагаемых, т.е. переменная z может принимать только два значения: 1 или -1. Вычислять это проще всего по формуле:
z = -z;
Естественно, до начала суммирования переменная z должна получить необходимое значение (в нашем случае z=1).
Возможная реализация программы:
#include <iostream>
using namespace std;
int main()
{
double i, p, s = 0, z = 1;
int n = 10;
for(i = 2; i <= n + 1; i++)
{
p = z * (i * i - 1) / (i * i * i);
s += p;
z = -z;
}
cout << "s=" << s << endl;
return 0;
}
|
|
|