Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
основы программирования на Паскале.doc
Скачиваний:
255
Добавлен:
25.03.2016
Размер:
4.34 Mб
Скачать

13. Решение учебных задач на циклы

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

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

Пр. Задана функция и ее разложение в ряд:

n=0,1,2,… (здесьn! обозначает факториал числаn, равный 1*2*3*….*n; при этом 0!=1). Найти число элементов рядаk, требуемое для достижения заданной точности ε.

Это – типичная задача на ряды. С ростом nслагаемыестановятся все меньше, равно как и модуль разности между двумя соседними слагаемыми. Поэтому под достижением заданной точности будем понимать выполнение условиягдеSn,Sn-1– суммы ряда, вычисленные на текущем и предыдущем шагах цикла, ε задается малым числом, от 10-6и ниже. Для вычисленияx2nвведем переменнуюxn, которую на каждом шаге цикла будем домножать наx2, аналогично, для вычисления текущего значения факториала используем переменнуюnf. Иной подход потребовал бы большого количества повторных вычислений на каждом шаге цикла, плюс был бы чреват большими потерями точности. Для вычисления (-1)nбыло бы странно использовать формулуax=exln a– вполне достаточно завести целочисленную переменнуюznak, равную1, которая на каждом шаге цикла будет менять свое значение на противоположное операторомznak:=-znak;. Кроме того, так как требуемое число шагов заранее неизвестно, используем для всех основных переменных более точный типdoubleвместоreal.

Реализуем все сказанное в следующей программе:

{$N+} {Директива режима совместимости с 80287 - для использования double}

var x,sn,sn1,xn,nf,eps:double;

k,n:longint;

znak:integer;

begin

writeln ('Введите значение x для разложения в ряд:');

read (x);

writeln ('Введите требуемую точность:');

read (eps);

sn1:=0;

sn:=0;

k:=0;

n:=0;

xn:=1;

nf:=1;

znak:=1;

repeat

sn1:=sn; {Текущая сумма стала предыдущей для следующего шага}

sn:=sn+znak*xn/nf; {Выполняем шаг цикла}

{Меняем переменные для следующего шага:}

znak:=-znak;

xn:=xn*sqr(x);

nf:=nf*(n+1)*(n+2);

n:=n+2;

k:=k+1;

until abs(sn1-sn)<eps;

writeln ('Точное значение функции=',cos(x):20:16);

writeln ('Предыдущая сумма=',sn1:20:16);

writeln ('Текущая сумма=',sn:20:16);

writeln ('Число шагов=',k);

reset (input); readln;

end.

До главы "Графика" еще далеко, но даже в обычном текстовом режиме работы можно наглядно проиллюстрировать результаты своих расчетов. Рассмотрим в качестве примера задачу:

Пр. Сформировать на экране изображение функции

f(x)= cos(x)+ln(x)

на интервале [1,5] с шагом 0.2.

Программа с подробными комментариями приводится ниже:

var x,y, { Значение аргумента и функции }

a,b, { Интервал }

ymin,ymax:real; { Минимальное и максимальное Y }

cy, { Позиция столбца на экране }

i:integer; { Счетчик для цикла for }

begin

a:=1;

b:=5;

{ Первый цикл нужен, чтобы определить минимальное и максимальное

значение функции на заданном интервале }

x:=a; { Начинаем с левой границы }

ymin:=1e20; ymax:=1e-20; { Минимуму присваиваем большое число,

максимуму - маленькое }

while x<=b do begin { Пока x не превысило правой границы }

y:=cos(x)+ln(x); { считаем очередное значение функции }

if y<ymin then ymin:=y { Ищем минимум }

else if y>ymax then ymax:=y; { Ищем максимум }

x:=x+0.2; { Переходим к следующему x }

end; { Конец первого цикла }

{ Во втором цикле обработки можно выводить на экран значения функции }

x:=a;

while x<=b do begin { Пока x не превысило правой границы }

y:=cos(x)+ln(x); { считаем очередное значение функции }

cy:=Round ( 8+(y-ymin)*(70/(ymax-ymin)) );

{ Чтобы пересчитать y из границ [ymin,ymax] в границы [8,78] (столбцы

экрана, в которые выводим график), используем формулу

78 - 8

cy= 8 + (y-ymin) * -----------

ymax - ymin

Теперь в переменной cy - нужный нам столбец экрана }

writeln; { Переходим к новой строке на экране }

write (x:7:3,' '); { Выводим значение x и пробел }

for i:=8 to cy do write ('*'); { Рисуем звездочками значение y }

x:=x+0.2; { Переходим к следующему x }

end; { Конец второго цикла }

end.

Пр. Проверить, является ли введенное положительное целое числоNпростым.

Очевидно, что простое число делится без остатка только на единицу и само на себя. В цикле последовательно проверим остатки от деления Nна числа 2,3,…,N-1. Если найден хотя бы один остаток, равный нулю, число не является простым и дальнейшие проверки бессмысленны. Обратите внимание на использование логической переменной-флагаsв этой программе.

var n,i:longint;

s:boolean;

begin

write ('N=');

readln (n);

s:=true;

for i:=2 to n-1 do

if n mod i = 0 then begin

s:=false;

break;

end;

if s=true then writeln ('простое')

else writeln ('НЕ простое');

end.