русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Функции пользователя. Рекурсивные функции


Дата добавления: 2015-07-23; просмотров: 1362; Нарушение авторских прав


Функция как объект языка Паскаль является другой версией реализации технологии построения программ с использованием структуры группирования. Можно также сказать, что функция есть частный вид определенного типа процедур, а именно процедур с одним параметром-переменной.

 

5.2.1. Определение функции

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

 

Общая форма записи заголовка функции

 

FUNCTION имя (список параметров: тип): тип;

или

FUNCTION имя : тип;

 

 

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

 

 

Рис. 33. Синтаксическая диаграмма заголовка функции

Итак, заголовок функции отличается от заголовка процедуры не только сменой слова PROCEDURE на FUNCTION, но и удалением из списка параметров параметра-результата с присвоением его типа имени функции:

PROCEDURE <имя процедуры> (аргументы;
VAR параметр-результат: тип);

 

FUNCTION <имя функции> (аргументы): тип;

 

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

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



 

5.2.2. Функции пользователя

 

Известно, что Паскаль имеет набор стандартных функций. Однако этот набор ограничен. Пользователь может по желанию расширить список функций, создав свои функции – функции пользователя. Так, например, в Паскале есть SQR (X) = X2, а вот функции F (X) = Xn, где n принадлежит множеству целых чисел Z, нет. Используя определенное ранее понятие функции, можно создать для этого универсальную функцию, которая давала бы степени произвольного вещественного числа с любым целым показателем.

Определим вещественную функцию POWER, которая должна иметь два параметра-аргумента – для показателя и для основания степени:

 

function POWER (FACTOR: real; EXP: integer): real;

var COUNT: integer; TFACTOR: real;

begin

if EXP = 0 then POWER := 1

else begin

TFACTOR := FACTOR;

for COUNT := 2 to ABS (EXP) do

TFACTOR := TFACTOR*FACTOR;

if EXP < 0 then POWER := 1/TFACTOR

else POWER := TFACTOR

end

end;

 

Теперь можно эту функцию вызывать следующим образом:

а) F := POWER(5.25, 3);

б) WRITELN ("D = ", POWER (5.25, -2):5:2);

в) IF X > 2*POWER (6.2, 3) THEN WRITE ('ДА');

г) A := POWER (X, 2) + POWER (X, 3) + POWER (X, 4).

5.2.3. Рекурсивные функции

 

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

В математике известно рекурсивное определение факториала:

 

n! = 1 при n = 0;

n! = (n - 1)! × n при n > 0.

 

Это рекурсивное определение можно реализовать с помощью соответствующей рекурсивной функции:

 

function FACTORIAL (VALUE: integer): integer;

begin

iF VALUE = 0 then FACTORIAL := 1

else FACTORIAL := VALUE*FACTORIAL (VALUE - 1)

end;

 

Теперь можно обращаться к этой функции в теле основной программы, как показано в следующем примере:

 

program FINDFACTORIAL;

var N: integer;

begin

writeln ('Введите число');

readln (N);

if N < 0 then writeln ('Нет факториала')

else writeln ('Факториал ', N, ' равен ', FACTORIAL (N))

end.

 

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

 

FACTORIAL := VALUE*FACTORIAL (VALUE - 1),

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

Важным моментом при составлении любой рекурсивной функции является организация выхода из рекурсии. В некоторых простых случаях должно существовать не рекурсивное решение. Рекурсивный процесс должен шаг за шагом так упрощать задачу, чтобы, в конце концов, для нее появилось не рекурсивное решение. В этих функциях должны проверяться значения аргумента для принятия решения о завершении. В нашем случае условием завершения рекурсии является VALUE = 0.

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

Рассмотрим рекурсивный процесс на примере вычисления факториала для N = 3. Получим следующие шаги:

1. N = 3, где N <> 0. Тогда FACTORIAL := 3*FACTORIAL (2);

2. N = 2, где N <> 0. Тогда FACTORIAL := 2*FACTORIAL (1);

3. N = 1, где N <> 0. Тогда FACTORIAL := 1*FACTORIAL (0);

4. N = 0, следовательно, FACTORIAL := 1,

т.е. получили не рекурсивное значение. Углубление в рекурсию закончено, далее пойдет процесс выхода из нее с выполнением необходимых вычислений.

В выражение 1*FACTORIAL (0) вместо FACTORIAL (0) подставляется его значение 1, вычисляется произведение 1*1, которое становится значением FACTORIAL (1). В выражение 2*FACTORIAL (1) вместо FACTORIAL (1) подставляется значение 1, вычисляется 2*1 и становится значением FACTORIAL (2). В выражение 3*FACTORIAL (2) вместо FACTORIAL (2) подставляется значение 2, вычисляется 3*2 и становится значением переменной FACTORIAL, которая возвращает в основную программу значение 3!.

Весь этот двухэтапный рекурсивный процесс реализуется в памяти ЭВМ с помощью организации в ней стека рекурсии. Дело в том, что для хранения значений переменной N (а значит и переменной VALUE) отводится не одна ячейка, а стек с именем N. В этот стек последовательно заносятся значения 3, 2, 1, 0, причем значение 0 есть признак конца заполнения стека. Затем начинает работать цикл с телом FACTORIAL := FACTORIAL*N, где значения N выбираются последовательно из стека в порядке 1, 2, 3. Исходным же значением переменной FACTORIAL является единица, являющаяся значением 0!.

Работа стека представлена в таблице:

 

Заполнение стека (углубление) Стек № Вычисление (разуглубление)
FACTORIAL := 1 FACTORIAL := 1
FACTORIAL := 1*FACTORIAL (0) FACTORIAL := 1*FACTORIAL
FACTORIAL := 2*FACTORIAL (1) FACTORIAL := 2*FACTORIAL
FACTORIAL := 3*FACTORIAL (2) FACTORIAL := 3*FACTORIAL

 

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

Данная функция явно носит рекурсивный характер, исходя из ее определения:

 

Xn = 1, если n = 0;

Xn = Xn-1 * X, если n > 1.

 

Ниже следует рекурсивная функция вычисления значения степени:

function POWER (FACTOR: real; EXPONENT: integer): REAL;

begin

if EXPONENT < 0

then POWER := 1/POWER (FACTOR, abs (EXPONENT))

else

if EXPONENT > 0

then POWER := FACTOR*POWER (FACTOR, EXPONENT - 1)

else POWER := 1

end;

 

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

 

procedure FACTORIAL (VALUE: integer; var F: integer);

begin

iF VALUE = 0 then F := 1

else begin FACTORIAL (VALUE - 1, F);

F := F*VALUE

end;

end;

 

Здесь уже, в отличие от функции FACTORIAL, для вычисления N! необходимо вызвать эту процедуру с помощью оператора процедуры FACTORIAL (N, FN), где FN – переменная для возвращения из процедуры значения N!.

Контрольные вопросы

1. Какие виды подпрограмм используются в языке Паскаль?

2. На какие два типа принято подразделять процедуры?

3. Где располагаются встроенные процедуры и что нужно написать в разделе объявлений, чтобы вызывать их в нужном месте программы пользователя?

4. В каком разделе программы помещаются процедуры пользователя?

5. Какова роль параметров процедуры?

6. Чем отличаются параметры-переменные от параметров-значений?

7. Чем отличаются фактические параметры от формальных параметров?

8. Где объявляются локальные и глобальные переменные?

9. Каким образом в программе вызывается процедура?

10. В чем отличие заголовка процедуры от заголовка функции?

11. Какой переменной обязательно присваивается значение в теле функции?

12. Как в программе вызывается функция?

13. Что является отличительной чертой рекурсивной функции?

14. Каким образом в рекурсивной функции осуществляется выход из рекурсии?

15. Задачи какого типа лучше реализовывать с помощью рекурсивных функций?



<== предыдущая лекция | следующая лекция ==>
Процедуры и их типизация | Задания для самостоятельной работы


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.78 сек.