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

Задачник-практикум по основам программирования. Учебное пособие по курсу «Информатика»

.pdf
Скачиваний:
0
Добавлен:
12.08.2026
Размер:
1 Мб
Скачать

7. ПРОЦЕДУРНЫЙ ТИП

Процедурный тип описывает класс процедур или функций, имею- щих однотипные заголовки, т.е. однотипные списки параметров. Имена формальных параметров не являются существенными в этих описаниях. Важно только их количество, порядок следования, типы и способ передачи, а также тип результата для функции [13].

Определение процедурного типа аналогично заголовку подпрограммы, но при этом имя подпрограммы не задается. Например,

type PROC1 = procedure (a, b, c: real; var d: real); PROC2 = procedure;

FUNC1 = function : real;

FUNC2 = function (x: real):real;

Введенный процедурный тип может быть использован при описании формальных параметров подпрограмм. Например,

procedure MENU (x, y: integer; SHOW: PROC2); function SUMMA(EPS: real; F: FUNC2);

Если подпрограмма имеет параметр процедурного типа, то при ее вы- зове в качестве фактического параметра должна использоваться процедура (функция), заголовок которой соответствует заголовку, описанному в про- цедурном типе. Это должна быть обязательно пользовательская процедура (функция), использовать в качестве фактического параметра стандартные функции нельзя.

Например, процедуры с такими заголовками: procedure PRINT; {соответствуют типу PROC2} procedure LINE;

могут быть использованы как фактические параметры при вызове процедуры MENU:

MENU(10, 20, LINE);

MENU(15, 20, PRINT);

Пример 7.1. Описать процедуру выдачи таблицы значений произволь- ной вещественной функции от одной вещественной переменной. Таблица получается на отрезке [a, b] с заданным шагом h. Считать, что функция на

121

отрезке определена и непрерывна. Используя процедуру, построить таблицы значений для двух функций f(x) = ex . sin(x) и g(x) = cos(x) [14].

program ProcType_1;

type func=function(x: real): real; {тип табулируемой функции}

var a, b, h: real ;

{ следующие две функции соответствуют типу func и будут

использованы в качестве фактических параметров при вызове

процедуры табулирования } function F(x: real): real; begin

F:=exp(x)*sin(x)

end;

function G(x: real): real; begin

G:=cos(x)

end;

procedure Tabulir (a, b, h: real; F: func); var x: real;

begin

writeln(‘Таблица значений функции на отрезке’);

writeln(‘-------------------------------

X

|

F(x)

’);

writeln(‘|

|’);

writeln(‘-------------------------------’);

x:=a;

 

 

 

 

while (x<=b+h/3) do

 

 

 

begin

 

 

 

 

writeln(‘|’,x:14:5,’|’,f(x):14:5,’|’);

x:=x+h

 

 

 

 

end;

 

 

 

’)

writeln(‘-------------------------------

 

 

 

end;

 

 

 

 

begin

 

 

 

 

writeln(‘Введите отрезок и шаг табулирования ’, ‘для первой функции’);

readln (a, b, h);

122

Tabulir(a, b, h, F);

writeln(‘Введите отрезок и шаг табулирования ’, ‘для второй функции’);

readln(a, b, h); Tabulir(a, b, h, G)

end.

Упражнения

1)Использовать процедуру Tabulir для получения таблиц значений

других функций.

Например, h(x) = x2+0.5x–7

2)Если ввести процедурный тип:

type isfunc=function(x:real):boolean;

то можно добавить в процедуре Tabulir еще один параметр проце- дурного типа:

procedure Tabulir (a, b, h: real; F:func; Iif: isfunc);

Вторая функция-параметр должна проверять, определена ли табули- руемая функция в заданной точке.

ВнестисоответствующиеизменениявпроцедуруTabulir, чтобымож- но было строить таблицу значений и для функций, имеющих особенности.

Проверить ее работу на примере функции f(x) = 1/x.

Пример 7.2. Для уравнения x=f(x) уточнить приближенное значение корня x0 методом итераций [15].

Метод итераций применим, если на отрезке между x0 и корнем

уравнения x* выполняется условие f (x) < 1. Тогда последовательные приближения к точному значению корня вычисляются в соответствии с рекуррентным соотношением

xn = f (xn1 ),

 

n > 0

 

x

 

0

Так как сходимость метода итераций зависит от вида функции и правильного выбора начального приближения x0, следует предусмотреть в функции, реализующей метод итераций, возможность прекращения вы- числений, если количество итераций превысит заранее заданное значение (например, 10000). При этом результат функции неопределен.

123

Обычно в таких случаях функцию описывают как логическую, ре- зультат которой зависит от того, найдено значение корня или нет. Само же вычисленное значение корня функция возвращает через параметр-пе- ременную.

program ProcType_2;

type func=function(x:real):real; var x0,kor:real ;

function MyF(x:real):real; begin

MyF:=sin(x)+0.25

end;

function Met_Iter(x0: real; eps: real; F: func; var xn: real):boolean;

const NMAX = 10000;

var xs:real; i:integer; begin

Met_Iter:=true; xn:=x0; i:= 1; repeat

i:=i+1;

xs:=xn;

xn:=F(xs)

until (abs(xn-xs)<eps) or (i>NMAX); if (i>NMAX) then Met_Iter:=false

end; begin

write (‘Введите начальное приближение ‘); readln(x0);

if Met_Iter(x0, 1e-8, MyF, kor) then writeln(‘приближенное значение корня’, kor)

else begin

writeln (‘Количество итераций превысило максимальное.’);

writeln(‘Условие сходимости не выполнено.’); end

end.

124

Контрольный пример

Входные данные: x0 = 1 Выходные данные: kor 1.171

Пример 7.3. Описать функцию вычисления приближенного значения

интеграла w = b f (x)dx , используя метод Симпсона с (n + 1) точкой разби-

a

ения интервала [a, b] [14]. Вычислить площадь криволинейной трапеции, ограниченной графиком функции cos(x)/x на отрезке [a, b].

Квадратурная формула Симпсона с (n + 1) точкой имеет вид:

b

f(x)dx h

[f(a)+4 f(a +h) + 2f(a +2h )+...+4f(a +(n 1))h + f(b)],

a

 

3

 

 

h = b a

,

n четное

 

n

 

 

program ProcType_3; const n=10;

type func = function (x: real): real; var w, a, b: real;

function MyF(x: real): real; begin

MyF:=cos(x)/x

end;

function Simps(a, b: real; n: integer; F: func): real;

var h, S:real;

i, c:integer; begin

S:=F(a)+F(b); h:=(b-a)/n; c:=4;

for i:=1 to n-1 do begin

S:=S+c*F(a+i*h);

if c=4 then c:=2 ELSE c:=4 end;

Simps:=S*h/3.0

end; begin

writeln(‘a=’); readln(a);

125

writeln(‘b=’); readln(b); w:=Simps(a,b,n,MyF); writeln(‘Интеграл=’,w:10:4)

end.

Контрольный пример

Входные данные: a = 1, b = 2 Выходные данные: w 0.0856

Пример 7.4. Изменить функцию вычисления интеграла методом Сим- псона так, чтобы она уточняла приближенное значение интеграла, последо- вательно удваивая количество отрезков разбиения. Вычисления продолжать до тех пор, пока разность между приближенным значением, вычисленным для n отрезков разбиения и для 2n отрезков, не станет по модулю меньше eps ( 0 < eps << 1). Начальное количество отрезков разбиения равно 2.

При удвоении количества отрезков разбиения (2n) в квадратурной формуле будут использоваться значения подынтегральной функции, как

вновых точках, так и в точках, которые были получены для n отрезков разбиения. Чтобы не выполнять лишние вычисления значений функции

водних и тех же точках, представим квадратурную формулу в виде трех слагаемых, отличающихся коэффициентами:

b

f(x)dx h

[ 1

 

2

 

3 ].

+ 4S

+ 2S

 

S

 

 

a

3

 

 

 

 

 

ВпервоеслагаемоеS1 входяттолькодвазначенияфункции наконцахот- резка. Эта сумма не меняется при изменении количества отрезков разбиения.

Во второй сумме S2 участвуют значения функции в точках с четными номерами 2, 4,..., n. При удвоении количества отрезков разбиения, все точ- ки, значения в которых были вычислены до этого, становятся четными.

Втретью сумму S3 входят значения функции в точках с нечетными номерами. Это те точки, которые появляются при удвоении количества отрезков разбиения. Только в этих точках нужно вычислять новые значения функции. Все это можно записать в виде рекуррентных соотношений:

ni = 2 ni1, S1i = S1i1

 

 

 

 

S2

i

= S2

i1

+ S3

1

 

 

 

 

 

 

i

 

 

 

 

S3i

= f (x j ),

где j = 1, 3,...,

ni 1

 

 

 

 

 

 

 

 

j

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

= 0, S30 = f

a + b

n0 = 2, S10 = f (a) + f (b), S20

 

 

 

 

 

 

 

 

 

 

 

2

126

function Simps(a, b: real; eps: real; F: func):real; var h, S1, S2, S3, Sn, S2n:real;

n,i:integer; begin

n:=2; h:=(b-a)/2;

S1:=F(a)+F(b); S2:=0; S3:=F((a+b)/2); S2n:=h/3*(S1+4*S2+2*S3);

repeat Sn:=S2n;

n:=n*2; h:=h/2; S2:=S2+S3; S3:=0; i:=1; while i<n do begin

S3:=S3+F(a+i*h);

i:=i+2

end;

S2n:=h/3*(S1+4*S2+2*S3) until abs(Sn-S2n)<eps; Simps:=S2n

end;

Упражнения

1)Изменить программу ProcType_3 так, чтобы она использовала второй вариант функции Simps. Выполнить интегрирование для отрезка [9] при разных значениях eps ( 0 < eps << 1). Сравните полученные резуль- таты со значением, которое получается при фиксированном количестве интервалов разбиения. Провести такое же сравнение, изменяя количество отрезков разбиения.

2)Возьмите другой отрезок интегрирования, например, [9]. Провести для него такие же вычислительные эксперименты, как в упражнении 1).

Пример 7.5. Дано натуральное число n и последовательность из n целых чисел. Определить, сколько чисел в последовательности обладают одним из заданных свойств. Список свойств, предлагаемых на выбор, выдается в начале программы.

В качестве проверяемых свойств использовать следующие варианты: 1. Число является положительным.

127

2.Число является кратным трем.

3.Число начинается и заканчивается одной и той же цифрой. Решение задачи можно оформить в виде функции, которая выводит и

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

program ProcType_5;

type pred1=function(a:integer):boolean; function IsPositiv(a:integer):boolean; begin

IsPositiv:= a>0 end;

function TimesThree(a:integer):boolean; begin

TimesThree:= a mod 3 = 0 end;

function SameCifr(a:integer):boolean; var c1,cn:integer;

begin a:=abs(a);

c1:=a mod 10; {последняя цифра числа}

cn:=c1;

{если в числе только одна цифра}

while a<>0

do begin

cn:=a mod 10;

a:=a div

10;

end;

SameCifr:= c1=cn end;

function Kol(n: integer; isf: pred1): integer; var k, i, a: integer;

begin k:=0;

for i:=1 to n do begin

read(a);

if isf(a) then k:=k+1 end;

128

Kol:=k

end;

var n, vibor: integer; begin

repeat

writeln(′Выберите проверяемое свойство′); writeln(′1 – числа положительные′); writeln(′2 – числа кратны трем′);

writeln(′3 – числа начинаются и заканчиваются одной цифрой′);

readln(vibor)

until (vibor>=1) and (vibor<=3); write(′Количество чисел в последовательности ′); readln(n);

writeln(′Введите последовательность′); case vibor of

1:write(Kol(n,IsPositiv));

2:write(Kol(n,TimesThree));

3:write(Kol(n,SameCifr))

end;

writeln (′чисел обладают заданным свойством′)

end.

Упражнения

1)Изменить программу так, чтобы она определяла количество чет- ных чисел в последовательности. Учтите, что стандартную функцию odd нельзя передавать в качестве фактического параметра, поэтому нужно со- здать пользовательскую функцию, которая будет вызывать функцию odd

ивозвращать ее результат.

2)Реализовать функцию проверки свойства кратности любому задан- ному натуральному числу. Проверить заданную последовательность чисел на кратность 3, 5, 7, 11, 23.

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

129

{определение типа двуместного предиката} type pred2=function(a, b: integer):boolean; {примеры функций - предикатов}

function IsEqual(a, b: integer): boolean; begin

IsEqual:= a=b end;

function ChangeSign(a, b: integer): boolean; begin

ChangeSign:= (a*b)<0 end;

function Kol(n: integer; isf: pred2): integer; var k, i, ap,a: integer;

begin

k:=0; read(ap); for i:=2 to n do begin

read(a);

if isf(ap, a) then k:=k+1; ap:=a

end;

Kol:=k

end;

Использование описанных функций в программе будет выглядеть так:

Kol(n, IsEqueal); Kol(n, ChangeSign);

ЗАДАЧИ

7.1.Описать процедуру (процедуры), которая для произвольной вещественной функции от одной вещественной переменной на отрезке [a, b] с заданным шагом h определяет максимальное и минимальное значение функции и точки, в которых эти значения достигаются. Считать, что функция на отрезке определена и непрерывна. Использовать процедуру в программе, определяющей минимальное/ максимальное значение для следующих функций:

y =

x2

 

 

, [1, 1] y = ln(x2

+ 1),

[1, 3].

0.5x2

1

 

 

 

 

130

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]