Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2575.pdf
Скачиваний:
2
Добавлен:
15.11.2022
Размер:
1.86 Mб
Скачать

14. ФУНКЦИИ И ПРОЦЕДУРЫ

Вспомогательные алгоритмы организуются двумя способами в зависимости от использования:

Процедуры

Программа процедура предназначена для выполнения какой-то законченной последовательности действий. Любая процедура начинается с заголовка. В отличии от основной программы заголовок в процедуре обязателен. Он состоит из зарезервированного слова Procedure, за которым следует идентификатор имени процедуры, а далее в круглых скобках список формальных параметров:

Procedure <имя процедуры> (список формальных параметров)

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

Procedure < имя процедуры >[(< аргументы >: < тип аргументов>]; Var <значение>:< тип значения >] )];

Var < переменная 1>[,< переменная 2>,...]: тип;

Begin

< тело процедуры>;

End;

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

87

Функции

Подпрограмма-функция предназначена для вычисления какого-либо параметра. У подпрограммы-функции два основных отличия от процедуры:

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

б) в теле функции хотя бы раз имени функции должно быть присвоено значение.

Function < имя функции >[(< аргументы >: < тип аргументов>):< тип значения функции>];

Var < переменная 1>[,< переменная 2>,...]: тип;

Begin

<тело функции>; <имя функции>:=<выражение значение функции>;

End;

Примеры решений задач

1. Пример функции для вычисления факториала.

Function Factorial(N:Byte):Longint;

Var

Fact:longint; I:byte;

Begin

Fact:=n;

For i:=n-1 downto 2 do

Fact:=fact*i; Factorial:=fact;

88

End;

Рекурсия

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

При анализе рекурсивной программы возникает, как обычно, два вопроса:

(а) почему программа заканчивает работу?

(б) почему она работает правильно, если заканчивает работу? Для (б) достаточно проверить, что (содержащая

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

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

Напишем рекурсивную процедуру вычисления факториала целого положительного числа n

(т. е. произведения , обозначаемого n! ).

Решение. Используем равенства 1!=1 , .

procedure factorial (n: integer; var fact: integer);

| {положить fact равным факториалу

числа n}

begin

| if n=1 then begin

89

| | fact:=1;

| end else begin {n>1}

| | factorial (n-1, fact); | | {fact = (n-1)!}

| | fact:= fact*n; | end;

end;

С использованием процедур-функций можно написать так: function factorial (n: integer):

integer;

begin

| if n=1 then begin | | factorial:=1;

| end else begin {n>1}

| | factorial:= factorial (n-1)*n; | end;

end;

Обратите внимание на некоторую двойственность использования имени factorial внутри описания функции: оно обозначает как переменную, так и вызываемую рекурсивно функцию. К счастью, в нашем случае они различаются по скобкам после имени, но если бы функция была без параметров, то дело было бы плохо. (Стандартная, но трудно находимая ошибка возникает, если автор программы на паскале полагает, что он использует значение переменной, а компилятор в этом месте видит рекурсивный вызов).

Количество делителей. Составить рекурсивную программу-функцию подсчета количества всех положительных делителей натурального числа n.

Решение. Перейдем к более общей задаче. Подсчитаем для натурального числа n количества всех его положительных делителей, меньших или равных заданному натуральному числу x. Пусть dn(n) и dnx(n,x) соответственно функции для решения исходной и обобщенной задач. Очевидно, что dn(n)=dnx(n,n).

90

Рекурсивную функцию dnx(n,x), по которой последовательно подвергаются испытанию на делители n все числа от 1 до x включительно, можно определить так:

Трудоемкость вычислений алгоритма решения задачи с использованием функции dn(n) составляет O(n) арифметических операций. Более эффективно эти вычисления можно проводить с помощью пары функций:

Рекурсивная функция dnx2(n,x) аналогична функции dnx(n,x), но подсчитывает удвоенное количество делителей n, не превосходящих x.

Функция dns(n), организуя выбор величины x, обращается к dnx2(n,x) соответственно с x=sq 1 или с x=sq

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

Трудоемкость вычислений по dns(n) составляет арифметических операций.

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

91

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