Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Рекурсия и опережающее описание




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

Рассмотрим классический пример - вычисление факториала.

Программа вводит с клавиатуры целое число N и выводит на экран значение N!, которое вычисляется с помощью рекурсивной функции РАС.

Для выхода из программы необходимо либо ввести достаточно большое целое число, чтобы вызвать переполнение при умножении чисел с плавающей запятой, либо нажать Ctrl-Z и Enter.

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

В примере решение при N = 0 тривиально и используется для остановки рекурсии.

Program Factorial;

{$S+} {Включаем контроль переполнения стека}

var

n: Integer;

Function Facfn: Integer): Real;

{Рекурсивная функция, вычисляющая n! }

begin {Fac}

if n < 0 then

WriteLn ('Ошибка в задании N')

else

if n = 0 then

Fac:= 1

else Fac:= n * Fac(n-l)

end {Fac};

{---------------}

begin {main} repeat

ReadLn (n);

WriteLn ('n!= ',Fac(n))

until EOF

end {main}.

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

Если, например, попытаться заменить тип REAL функции FAC на EXTENDED, программа перестанет работать уже при N = 8.

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

Вот правильный вариант примера для работы с типом EXTENDED:

Program Factorial;

{$S+,N+,E+} {Включаем контроль Стека и работу сопроцессора}

var

n: Integer;

Function Fac(n: Integer): extended;

var

F: extended; {Буферная переменная для разгрузки стека сопроцессора}

{Рекурсивная функция, вычисляющая п! }

begin {Рас}

if n < 0 then

WriteLn ('Ошибка в задании N') else

if n = 0 then

Fac:= 1 else begin

F:= Fac(n-l); Fac:= F * n end end {Fac};

{--------------}

begin {main}

repeat

ReadLn (n);

WriteLn ('n! = ',Fac(n))

until EOF

end {main}.

Рекурсивный вызов может быть косвенным.

В этом случае подпрограмма обращается к себе опосредованно, путем вызова другой подпрограммы, в которой содержится обращение к первой, например:

Procedure A (i: Byte);

begin

В (i);

.......

end;

Procedure В (j: Byte);

begin

A(j);

end;

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

Для того, чтобы такого рода вызовы стали возможны, вводится опережающее описание:

Procedure В(j: Byte); forward;

Procedure A(i: Byte);

begin

.......

В (i);

.......

end;

Procedure В;

begin

.......

A(j);

.......

end;

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

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

Обратите внимание: тело процедуры

В начинается заголовком, в котором уже не указываются описанные ранее формальные параметры.

 





Поделиться с друзьями:


Дата добавления: 2016-11-18; Мы поможем в написании ваших работ!; просмотров: 455 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Есть только один способ избежать критики: ничего не делайте, ничего не говорите и будьте никем. © Аристотель
==> читать все изречения...

2188 - | 2139 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.007 с.