Все описанные в данном тексте алгоритмы устроены по единой схеме. Здесь описывается эта схема.
Ряды
В данной работе нам нужно суммировать ряды вида
(1) s0 = 0; sn+1 = sn + tn, n > 0;
в качестве условия останова фигурирует
(2) |sn+1 - sn| Ј e ,
где e – требуемая точность счета.
Отметим, что для некоторых – в частности, знакопеременных – рядов известным еще из школы критерием достижения нужной точности является
(3) |tn| Ј e .
Однако, вычисления производятся с конечной разрядностью, и потому при уравнивании порядков, необходимом для выполнения операции сложения, прибавляемая к sn величина t n+1 может и не совпадать с tn+1 (т.к. tn << sn-1, то при достаточно больших n обязательно будет t n < tn). При этом условие (3) начинает выполняться позже условия (2), означающего, что t n+1 Ј e Поэтому во всех алгоритмах условием останова является именно (2); это приводит к уменьшению числа суммируемых членов ряда.
Машинные эксперименты показали, что использование (3) в качестве условия останова лишь увеличивает время счета, не увеличивая в рассмотренных алгоритмах точность вычислений.
Алгоритмы, основанные на применении рядов, все имеют следующую структуру:
Отметим, что если в условии останова цикла (шаг P3) строгое неравенство заменить на нестрогое, то при e = 0 (т.е. при вычислениях с машинной точностью) алгоритм зациклится.
В нескольких алгоритмах, в которых приходится суммировать «плохо определенные» ряды с знакопеременными членами, условием останова является
(4) abs(sn - sn+1) Ј e && abs(sn+1 - sn) Ј e.
Цепные дроби
Цепные дроби удобны во многих теоретических и прикладных исследованиях. Они, в частности, используются в различных приближенных вычислениях. С их помощью можно, например, вычислять значения функций, причем очень часто алгоритм, основанный на подобном разложении, сходится быстрее, чем алгоритм, основанный на разложении функции в степенной ряд.
Цепной, или непрерывной, дробью называется выражение
(5)
или
Лично я предпочитаю обозначение (5).
Дробь называется n-м звеном цепной дроби; an и bn – членами ее n-го звена; a1, a2,… называют ее частными числителями, а b1, b2,… – ее частными знаменателями; b0 называют нулевым звеном цепной дроби.
Конечная цепная дробь
(6)
называется n-й подходящей дробью дроби (5). Я опишу здесь три способа, которые можно использовать для вычисления (6).
Способ 1
Этот способ состоит в последовательном осуществлении указанных в (6) действий. Формально процесс можно выразить следующими соотношениями
(7) rn-i = bn-i + sn-i+1, sn-i = an-i/rn-i, i = 0, 1, …, n-1,
где s0 = 0. При этом n-я подходящая дробь wn = b0 + s1.
Метод легко программируется, однако, обладает очевидным недостатком: при изменении n весь процесс нужно начинать с самого начала. А так как достигаемая точность определяется выбранным значением n, то при использовании этого способа приходится выбирать его настолько большим, чтобы обеспечить требуемую точность в наихудшем возможном случае. При этом, часто приходится производить лишние вычисления, которые могут оказаться довольно значительными. Мне известен лишь один пример успешного применения этого способа вычисления цепных дробей: при выводе формул вычисления элементарных функций для стандартных библиотек.
Способ 2
В этом способе n-я подходящая дробь вычисляется как отношение pn/qn, причем pn и qn находят из основных рекурсивных соотношений (см., например, [6]):
(8)
Преимущество этого метода по сравнению с предыдущим состоит в том, что на каждом этапе вычисленную подходящую дробь можно сравнить с ранее вычисленными приближениями и, если нужная точность достигнута, остановить процесс.
Недостатком его является то, что величины pn и qn очень быстро возрастают, если an >1, bn >1, и быстро убывают, если an <1, bn <1. А это может привести либо к переполнению, либо к необходимости деления на (машинный) нуль. Для борьбы с этим применяются разнообразные нормировки, которые лишают алгоритм прозрачности и увеличивают распространяемую ошибку; тем не менее, бывают ситуации, когда без этого не обойтись.
Способ 3
Здесь для n-й подходящей дроби используется следующее соотношение
(9) ,
в котором
(10) rk = ak/(bk-1bk), 1+ rk+1 = 1/(1 + rk+1(1+ rk)), k і 2,
причем r1 = r1 = a1/b1, 1+ r2 = 1/(1 + r2).
Этот метод обладает тем же достоинством, что и метод 2: подходящие дроби получаются рекурсивным способом, что позволяет следить за достигнутой точностью. Вместе с тем, при вычислениях не возникают ни слишком большие, ни слишком малые числа, поэтому этот метод представляется наиболее предпочтительным.
Поскольку соотношения (9)-(10) почти не встречаются в имеющейся на русском языке литературе, приведу здесь их вывод.
Широко известно следующее равенство (см., например, [6]):
(11) .
Положим и рассмотрим отношение rn+1 =An-1/An. Имеем
Алгоритмы, основанные на разложении функции f(x) в цепную дробь, имеют в данном тексте следующую структуру:
Комментарии
Суммирование ряда (11) производится здесь на основе алгоритма P с условием останова (4).
Если бы для вычисления мы использовали соотношения (8), шаги F1 и F2 алгоритма приняли бы вид:
Дальнейшие сведения о цепных дробях и их приложениях можно почерпнуть из книг [3, 6]; изложение способов вычисления цепных дробей, а также множество поучительных численных примеров вы найдете в статье [14].