Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Мансуров. Основы программирования в среде Lazarus. 2010

.pdf
Скачиваний:
45
Добавлен:
27.04.2021
Размер:
6.3 Mб
Скачать

Глава 2 Введение в язык программирования Pascal

____________________________________________________________________

рых мы будем говорить в главе 6, частности в разделе, посвященном исключе-

ниям.

2.1.26 Вычисление сумм сходящихся рядов

Вычислить сумму ряда

S

1

1

1

....

1

... ,

 

 

 

 

 

 

x

 

x2

 

x3

xn

 

 

 

 

 

 

х [1.5, 2] с шагом h=0.5, точность =10 –5

Составим блок-схему алгоритма:

начало

x=1.5; h=0.5; ε =10-5

нет

x<2

да

s=0; t=1;

t=t∙1/x;

s=s+t;

t< ε

нет

конец

да

x, s

x=x + h;

Рис. 2.57. Алгоритм вычисления суммы ряда

Из этой блок-схемы мы видим, что циклы могут быть вложены друг в дру-

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

ны все значения x.

131

en ln( x )

2.1 Основные элементы языка

____________________________________________________________________

Запись s=s+t следует рассматривать в "динамике", т.е. к текущему значе-

нию суммы s прибавляется очередной член ряда t и полученное значение снова запоминается в переменной s. Таким образом в переменной s накапливается сумма ряда.

Теперь, что означает вычислить сумму ряда с точностью ε. Это значит, что мы округляем вычисленную сумму ряда с числом знаков после запятой указан-

ной в ε. То есть, если очередной член ряда окажется меньше ε (вообще говоря,

по абсолютной величине), то добавление этого члена в сумму не окажет влия-

ния на результат и не скажется на итоговой сумме, поскольку мы его округля-

ем с заданной точностью ε.

Все эти рассуждения верны для сходящихся рядов, вычисление суммы рас-

ходящегося ряда не имеет смысла.

Рассмотрим в блок-схеме фрагмент, где вычисляется очередной член ряда t. Многие здесь допускают типичную ошибку. Для вычисления xn используют формулу xn . Так можно вычислять степень, но при таком способе ваша программа будет выполняться по времени на порядок дольше, чем при способе,

примененном нами. Ведь используя вышеприведенную формулу, вы заставляе-

те компьютер вычислять xn при каждом новом n как бы заново, с нуля. Но при-

смотритесь внимательно к ряду. Чтобы вычислить очередной член ряда надо

предыдущий член ряда умножить на 1x . И все!

Хотя на современных компьютерах разница во времени выполнения для таких простых программ практически не заметна, приучайтесь писать програм-

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

program summ;

{$mode objfpc}{$H+}

uses

132

Глава 2 Введение в язык программирования Pascal

____________________________________________________________________

CRT, FileUtil; var

x, s, h, eps, t: real; begin

x:= 1.5; h:= 0.5;

eps:= 0.0000000001; while x <= 2 do begin

s:= 0; t:= 1; repeat

t:= t * 1/x; s:= s + t; until t <= eps;

writeln('X= ', X:0:2, ' S= ', S:0:5); x:= x + h;

end;

writeln(UTF8ToConsole('Нажмите любую клавишу')); readkey;

end.

Вычислить значения функции sinx

используя его разложение в ряд

Тейлора:

 

 

 

 

 

 

 

 

x3

 

x5

 

x7

 

sin x x

 

 

 

 

 

....

 

3!

5!

7!

 

 

 

 

х [0,1], значения x заданы в радианах, h=0.2, точность =10 –7

Вывести также "точное" значение функции, вычисленное с помощью стандартной встроенной функции Паскаля sin(x)

Составление блок-схемы алгоритма предоставляется самому читателю.

133

2.1 Основные элементы языка

____________________________________________________________________

Здесь сложности может вызвать только процесс организации вычислений для определения очередного члена ряда по уже вычисленному предыдущему члену.

Внимательно проанализируйте ряд, включите "соображалку" и вы без труда придумаете, как это сделать. Рекомендую также не спешить смотреть програм-

му, а попытаться самому написать и отладить ее!

program sinus; {$mode objfpc}{$H+} uses

CRT, FileUtil; var

x, y, s, h, eps, t: real; n: integer;

begin x:= 0;

h:= 0.2; eps:= 1e-7;

while x <= 1 do begin

s:= x; t:= x; n:= 2; repeat

t:=-t * sqr(x)/(n * (n + 1)); s:= s + t;

n:= n + 2;

until abs(t) < eps; y:= sin(x); writeln('x= ', x:0:2,

134

Глава 2 Введение в язык программирования Pascal

____________________________________________________________________

UTF8ToConsole('Приближенное значение синуса = '), s:0:7, UTF8ToConsole('Точное значение синуса = '),

y:0:7);

x:= x + h;

end;

writeln(UTF8ToConsole('Нажмите любую клавишу'));

readkey;

end.

Как проверить, правильные результаты выдает программа или нет? Можно использовать так называемые модельные исходные данные, при которых априо-

ри известно, какими должны быть результаты. Для синуса, например, известно,

что sin 0 0 , sin

 

1

. Если в этих точках ваша программа выдает правильные

2

 

 

 

результаты, можно с определенной долей уверенности считать, что ваша про-

грамма работает правильно.

Есть и другой способ – сравнить результаты, выдаваемые вашей програм-

мой с другой программой, которая решает ту же задачу.

В нашем случае мы использовали встроенную функцию sin(x). Важно пони-

мать, что эту функцию писали тоже люди, программисты, разработавшие Free Pascal. Скорее всего, они тоже использовали разложение функции sinx в

ряд. И у нас нет никаких оснований не доверять им! Поэтому будем считать,

что встроенная функция sin(x) "точная" и если наша программа выдает те же результаты, то, можно считать, что программа работает правильно.

135

2.2 Реализация некоторых алгоритмов главы 1.

____________________________________________________________________

2.2. Реализация некоторых алгоритмов главы 1.

Настало время для реализации алгоритмов разобранных в главе 1, в разде-

лах 1.1 и 1.3, кроме программы решения квадратного уравнения, которое, на-

деюсь, вы уже давно сами написали.

2.2.1 Программа решения задачи о поездах и мухе

program mukha; {$mode objfpc}{$H+} uses

CRT, FileUtil;

var d, v, v1, v2, x, y, s, t: real; F: boolean;

begin

{Блок определения исходных данных} {Можно заменить вводом их с клавиатуры.

Тогда программа станет более универсальной,

в том смысле, что можно задавать разные расстояния и скорости}

d:= 600; v:= 200; v1:= 40; v2:= 60; y:= d;

s:= 0;

F:= false; // сначала идем по правой ветке алгоритма while y > 1e-2 do

begin

if not F then

136

Глава 2 Введение в язык программирования Pascal

____________________________________________________________________

begin

// это правая ветка алгоритма

F:=

true;

t:= y/(v + v1);

end

 

else

 

begin

// это левая ветка

F:=

false;

t:= y/(v + v2); end;

x:= t * v; s:= s + x;

y:= y – t * (v1 + v2);

writeln('x= ', x:0:4, ' s= ', s:0:2); end;

writeln(UTF8ToConsole('Нажмите любую клавишу'));

readkey;

end.

2.2.2 Программа вычисления определенного интеграла

Напишем программу вычисления интеграла

2

sin xdx

0

по формуле Симпсона методом двойного пересчета. Напомним, что блок-схему вычисления интеграла мы рассматривали в 1.3.2.

program integral;

{$mode objfpc}{$H+}

137

2.2 Реализация некоторых алгоритмов главы 1.

____________________________________________________________________

uses

CRT, FileUtil;

var

a, b, h, x, s, s1, eps: real;

n, k: integer;

begin

{задаем интервал, на котором вычисляется интеграл} a:= 0;

b:= pi/2;

k:= 0; // при первом вычислении интеграла k=0

eps:= 1e-5; // заданная точность вычисления интеграла n:= 4; // начальное число точек разбиения интервала (a, b)

h:= (b - a)/n; // шаг вычисления подынтегральной функции while true do

begin x:= a;

x:= x + h; s:= 0;

while x < (b - h) do begin

s:= s + sin(x) + 2 * sin(x + h); x:= x + 2 * h;

end;

s:= 2 * s;

s:= (h/3) * (sin(a) + 2 * sin(b) + s); if k = 0

then begin

k:= 1;

138

Глава 2 Введение в язык программирования Pascal

____________________________________________________________________

s1:= s; h:= h/2; continue;

end else

if abs(s1 - s) > eps then begin

s1:= s; h:= h/2; continue;

end else

break;

end;

writeln(UTF8ToConsole('Значение интеграла s= '), s:0:4); writeln(UTF8ToConsole('Нажмите любую клавишу'));

readkey;

end.

При заданных пределах интегрирования значение интеграла s= 1.0000

Проверим правильность полученных результатов прямым вычислением инте-

грала.

2

 

 

2

 

 

 

 

0 sin xdx

cos

 

(cos(

 

) cos(0))

(0 1) 1

 

2

 

0

 

Изменим верхний предел интегрирования на b= , для этого в программе из-

мените оператор

b:= pi/2;

на

b:= pi;

139

2.2 Реализация некоторых алгоритмов главы 1.

____________________________________________________________________

Осуществите новый прогон программы. Получим ответ s= 2.0000

Снова проверим прямым вычислением интеграла:

sin xdx

cos

(cos( ) cos(0))

( 1 1) 2

0

 

0

 

И, наконец, попробуем сделать верхний предел интегрирования b= 4

Программа выдаст ответ s=0.2929, снова проверим:

4

 

 

 

 

 

 

 

 

2

 

 

 

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0 sin xdx

cos

 

(cos(

 

) cos(0))

(

 

 

 

1) 0.70710 1 0.2929

 

4

2

 

 

0

 

 

 

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

140