Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / Алгоритмы / Математика / Математическая статистика (теория вероятности) / Способы вычисления нормального распределения /
8  Perl
8  PHP
8  JavaScript
8  HTML
8  DHTML
8  XML
8  CSS
8  C / C++
8  Pascal и Delphi
8  Турбо Ассемблер
8  MySQL
8  CASE-технологии
8  Алгоритмы
8  Python
8  Обратная связь
8  Гостевая книга
Новости о мире


Приложение А: Вычисление рядов и цепных дробей - Программирование от RIN.RU
Приложение А: Вычисление рядов и цепных дробей

Все описанные в данном тексте алгоритмы устроены по единой схеме. Здесь описывается эта схема.


Ряды


В данной работе нам нужно суммировать ряды вида
,


где tn+1 = g(tn).


Вычисления производятся стандартным способом:


(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) в качестве условия останова лишь увеличивает время счета,
не увеличивая в рассмотренных алгоритмах точность вычислений.


Алгоритмы, основанные на применении рядов, все имеют следующую структуру:


/* P1 */   sum = term = t0;
           do
/* P2 */     term = g(term); s = sum; sum = s + term;
/* P3 */   while abs(s - sum) >
e ;
           return sum;


Рис. 1. Структура алгоритма, вычисляющего разложение в ряд.


Отметим, что если в условии останова цикла (шаг 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. Имеем


;


Здесь использовано соотношение (8). Но из (8) также следует qn+1= (qn- anqn-2)/bn


Положим .


Так как rn = - anqn-2/qn, получаем


rn+1= - rn+1(1+rn)/(1+rn+1(1+rn)).


Отсюда и из (11) следуют соотношения (9)-(10).


Алгоритмы, основанные на разложении функции f(x)
в цепную дробь, имеют в данном тексте следующую структуру: /*F1 */ t = b0; term = a1/b1; s = t+term; rho = 1/(1+a2/b1/b2);


        term = (rho-1)*term; sum = s+term; k=3;


        do


/*F2 */    r = ak/bk-1/bk; rho = 1/(1+r*rho);


           term = (rho-1)*term; t = s; s = sum; sum = s+term;


           k = k+1;


/*F3 */ while abs(t-s)> e & abs(s-sum)> e ;


        return sum;
Рис. 2. Структура алгоритма, вычисляющего цепную дробь.


Комментарии


Суммирование ряда (11) производится здесь на основе алгоритма P с условием останова (4).


Если бы для вычисления мы использовали соотношения (8), шаги F1 и F2 алгоритма приняли бы вид:


/*F'1 */ p0 = b0; q0 = 1; q1 = b1; p1 = p0*q1+a1; sum = p1/q1; k =
1;



и


/*F'2 */ k = k+1; t = bkp1+ak*p0; p0 = p1; p1 = t;


t = bk*q1+ak*q0; q0 = q1; q1 = t;


t = s; s = sum; sum = p1/q1;


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


Дальнейшие сведения о цепных дробях и их приложениях можно почерпнуть из книг [3, 6]; изложение способов вычисления цепных дробей, а также множество поучительных численных примеров вы найдете в статье [14].



 8  Комментарии к статье  8 8  Обсудить в чате

 
  
  
    Copyright ©  RIN 2003 - 2004      * Обратная связь