русс | укр

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

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

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

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


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

Рекурсия


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


End.

ReadLn;

ClrScr;

Begin

End;

Begin

End;

Begin

End;

Begin

End;

Begin

Uses CRT;

Program Param_func;

End.

ReadLn;

Begin

End;

Begin

Uses CRT;

Program Primer;

End.

ReadLn;

Begin

End;

Begin

Uses CRT;

Program Primer;

End.

ReadLn;

Begin

End;

Begin

Uses CRT;

Program Primer;

End;

Begin

End.

ReadLn;

Begin

End;

Begin

Uses CRT;

Program Global;

End;

End;

Begin

End.

ReadLn;

ClrScr;

Begin

Uses CRT;

Program Primer;

S := Geron(3.0, 4.0, 5.0);

End;

Подпрограммы-функции

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



Функции располагаются в основной программе между разделом описания переменных Var и Begin основной программы. Функции используются для вычисления единственного значения, присваиваемого имени самой функции. Это значение вычисляется внутри самой функции по нужному алгоритму с помощью переменных (аргументов), называемых формальными параметрами.

Как и все программы в Паскале, функция состоит из заголовка, блока описаний и блока операторов:

Function Geron(x, y, z : Real):Real; заголовок функции

Var p : Real; описание локальных переменных

Begin начало блока операторов

p := (x + y + z)/2.0;

Geron := Sqrt(p*(p – x)*(p – y)*(p – z)); вычисленное значениеприсваивается имени функции

Внимание! После оператора End ставится точка с запятой.

Эта функция вычисляет площадь треугольника по формуле Герона – по трем его сторонам.

Заголовок функции

Function Geron(x, y, z : Real):Real;

начинается со слова Function , за которым следует ее имя, в данном случае Geron. После имени функции в скобках перечисляются имена и типы аргументов функции – входных данных или формальных параметров. В данном случае это x, y, z типа Real. Если имеются формальные параметры нескольких типов, то они группируются по типам, а между типами ставятся точки с запятой. Заголовок заканчивается указанием типа самой функции, то есть типа результата, вычисляемого этой функцией. В данном случае это Real.

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

В данном случае формальные параметры x, y, z функции Geron заменяются соответственно фактическими аргументами 3.0, 4.0, 5.0 , для которых и вычисляется значение функции. Вычисленное значение присваивается имени самой функции Geron и далее - переменной s. В этом примере s = 6.0.

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

Var a, b, c, s : Real; описание фактических (глобальных) параметров

 

Function Geron(x, y, z : Real):Real; заголовок функции

Var p : Real;

p := (x + y + z)/2.0;

Geron := Sqrt(p*(p – x)*(p – y)*(p – z));

End; конец функции

 

Begin начало основной (головной) программы

a := 3.0; инициализация фактических параметров

b := 4.0;

c := 5.0;

s := Geron(a, b, c); обращение к функции с фактическими параметрами a, b, c

WriteLn(‘Площадь треугольника равна ’, s:6:2);

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

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

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

описание меток Label,

определение констант Const

определения типов Type

описание переменных Var

описание процедур и функций Function, Procedure

операторы функции Begin … End;

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

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

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

3. формальные и фактические параметры должны совпадать по порядку следования, количеству и типам,

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

5. формальные параметры не должны совпадать по имени:

Function Err(x, y: Word; a, b, y: Real): Real; ошибка!

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

Function Summa(x, y: Real): Real;

Var s : Real;

s := x + y; эта функция ничего не вычисляет!

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

Function Fact(n: Word): Word; n – формальный параметр

Var i, f : Word; i, f – локальные переменные

Begin эта функция вычисляет факториал

f:=1; заданного числа

For i:=1 To n Do

f := f * i;

Fact := f;

8. если в функции используется цикл с параметром (цикл For), то параметр цикла должен быть описан внутри этой функции, то есть он должен быть обязательно локальной переменной (предыдущий пример),

9. связь вызывающей (головной) программы с функцией может осуществляться как через формальные и фактические, так и через глобальные параметры. Глобальные параметры (переменные) не описываются ни в заголовке функции, ни внутри ее. Они описываются в вызывающей программе и существуют как в ней, так и в любой функции, вызываемой из этой программы. Глобальные переменные могут изменять свои значения как в вызывающей программе, так и внутри функции:

Var a, b, c, s : Integer; с -глобальная переменная

Function Sum(x, y : Integer) : Integer;

c := c + 1; изменение значения глобальной

Sum := x + y + c; переменной в функции

a := 1;

b := 1;

c := 1; инициализация глобальной переменной

s := c + Sum(a, b);

WriteLn(‘s=’, s);

После выполнения этой программы s = 5.

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

s := c + Sum(a, b);

и принимало значение s = 5. Поменяем местами слагаемые в этом операторе присваивания:

s := Sum(a, b) + c;

Казалось бы, результат измениться не должен, но после вычислений получим
s = 6 - значение глобальной переменной c изменилось внутри функции и стало равным с = 2, и с таким значением оно было добавлено в общую сумму в вызывающей программе.

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

· сегмент кода, в котором хранится программа в виде машинных команд,

· сегмент данных, в котором выделяется память под глобальные переменные,

· сегмент стека, предназначенный для размещения локальных переменных:

 

 

Размер каждого сегмента не может превышать 64Кбайт. Адреса сегментов хранятся во время выполнения программы в сегментных регистрах:

CS – адрес сегмента кода,

DS – адрес сегмента данных,

SS – адрес сегмента стека.

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

· время жизни глобальных переменных – от начала работы программы до ее завершения,

· если глобальные переменные не были инициализированы явным образом, то есть им не были присвоены начальные значения, то перед началом работы программы они обнуляются,

· время жизни локальных переменных – с момента вызова подпрограммы и до ее окончания,

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

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

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

Function Func(k: Word) : Word;

Const n: Word = 0; n – типизированная константа

Var i: Word;

WriteLn(‘i=’,i); неопределенное значение переменнойi

WriteLn(‘n=’,n);

n:= n + k;

Func:=n;

Переменной i будет присвоено заранее неизвестное значение. При первом обращении к функции переменная n, определенная в CONST, будет равна нулю, и при каждом последующем обращении она будет увеличиваться на k.

· время жизни такой переменной – время работы всей программы: значения этой переменной сохраняются между вызовами подпрограммы,

· область действия такой переменной – подпрограмма, в которой она описана, то есть вне подпрограммы к этой переменной обратиться нельзя,

10. локальные и глобальные переменные могут совпадать по имени; в этом случае в функции работают локальные переменные,

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

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

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

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

Var a, b, c : Integer;

Function Sum(x, y : Integer) : Integer; x, y – параметры-значения

x := x + 1; изменение значений формальных

y := y + 1; параметров в функции

Sum := x + y;

a := 1;

b := 1;

c := Sum(a, b);

WriteLn(‘a=’, a, ‘ b=’, b);

Входные значения фактических параметров x = 1, y = 1. После выполнения программы они останутся теми же, хотя внутри функции соответствующие им формальные параметры изменились,

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

 

Var a, b, c : Integer;

Function Sum(Var x, y : Integer) : Integer; x, y – параметры-переменные

x := x + 1; изменение значений формальных

y := y + 1; параметров в функции

Sum := x + y;

a := 1;

b := 1;

c := Sum(a, b);

WriteLn(‘a=’, a, ‘ b=’, b);

Входные значения фактических параметров x = 1, y = 1. После выполнения программы они изменятся и примут значения x = 2, y = 2.

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

Зачастую использование параметров-переменных может тоже привести к непредсказуемым результатам вычислений:

Var a, b : Integer;

Function Nemo(Var x : Integer; y : Integer) : Integer;
x – параметр-переменная,

y – параметр-значение

x := x + y;

a := y;

Nemo := x;

a := 1;

b := 2;

WriteLn(‘Nemo=’, Nemo(a, b),‘ a=’, a, ‘ b=’, b);

Результат работы программы:

Nemo=2 a=2 b=2

Значение переменной a будет испорчено, так как значения переменных a и x будут записываться в одной ячейке памяти, а функция Nemo вместо 3 примет значение, равное 2. Ошибки такого рада трудно найти, поэтому в функциях и не рекомендуется использовать параметры-переменные,

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

Function Func(x : 1..10; r : array [1..20] Of Real) : Real;

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

Type TCount = 20;

TVector = Array [1 .. TCount] Of Real;

TInterval = 1 .. 10;

а в заголовке функции использовать эти новые типы:

Function Func(x : TInterval; r : TVector) : Real;

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

ü их тип должен быть определен в разделе описания типов Type,

ü они не должны быть стандартными,

ü они не должны быть вложенными,

ü они должны иметь только параметры-значения,

ü они должны быть откомпилированы с использованием директивы компилятору {$F+} – использование дальнего типа вызова подпрограмм.

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

Type TFunс = Function (x, y: Integer): Integer; описан процедурный тип TFunc – целой функции двух аргументов целого типа

Var a, b, c: Integer;

{$F+} директива компилятору- использование дальнего типа вызова подпрограмм

Function Add(x, y: Integer): Integer; функция для сложения двух переменных

Add := x + y;

Function Mult(x, y: Integer): Integer; функция для перемножения двух переменных

Mult := x * y;

Function Funny(x, y: Integer): Integer;

Funny := (x + y) * (x - y);

{$F-} отменадирективы

функция, использующая параметр-функцию operation

Function Par_func(m, n : Integer; operation : TFunc): Integer;

Par_func := operation(m, n);

a := 5;

b := 3;

c := Par_func(a, b, Add); фактические параметры для параметров-функций не указываются!

WriteLn('c=', c);

c := Par_func(a, b, Mult);

WriteLn('c=', c);

c := Par_func(a, b, Funny);

WriteLn('c=', c);

На экран будет выведено:

с=8

с=15

с=16

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

 

Использование рекурсии в программировании базируется на рекурсивных математических определениях. Считается, что в математике рекурсивность как принцип определений используется с 1890 года. Впервые применил ее Д.Гильберт.

Основная идея рекурсии – определить некий объект через самого себя, по крайней мере, частично. Оказалось, что с помощью рекурсии удобно описывать различного рода последовательности, подчиняющиеся определенным закономерностям.

Например, вычисление факториала целого неотрицательного числа n! = 1·2·3·…·(n-1) · n . Кроме того, по определению, 0! = 1. Рекурсивное математическое определение факториала имеет вид:

1 при n = 0,

n!=

(n – 1)!·n при n > 0.

Последовательность чисел Фибоначчи имеет вид 1, 1, 2, 3, 5, 8, 13…

В ней два первых числа фиксированы и равны единице, а каждое последующее число равно сумме двух предыдущих. Рекурсивное математическое определение числа Фибоначчи с порядковым номером n имеет вид:

1 при n = 1,

Fn= 1 при n = 2,

Fn-2 + Fn-1 при n > 2.

Общей особенностью этих рекурсивных определений является то, что некий сложный объект определяется через себя же (рекурсивно обращается к себе же), но в более простом исполнении. Рекурсивные математические определения отличаются особой лаконичностью, что и подтверждается вышеприведенными примерами.

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

Рассмотрим последовательность факториалов целых чисел 0!, 1!, 2!, 3!,…, в которой ai = i!, i = 1, 2, 3,… Эту же последовательность можно представить в виде рекуррентной формулы: ai = ai-1·i, a0 = 1, i = 1, 2, 3… Эта формула задает последовательность, в которой каждый очередной член зависит непосредственно от предшествующего. Начальный член последовательности a0 задан прямою. Найдя член последовательности с порядковым номером i = n, мы тем самым решим задачу вычисления n!

Рекуррентная формула для вычисления числа Фибоначчи с заданным порядковым номером i = n практически не отличается от рекурсивного определения: Fi = Fi-2 + Fi-1 , F1 = 1 , F2 = 1 , i = 3, 4, 5,…

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

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

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

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

При рекурсивном обращении каждый раз приходится запоминать не только адрес возврата, но и всю совокупность данных вызывающей подпрограммы (локальные переменные и параметры-значения). С этой целью используется автоматически выделяемая область памяти – стек, структура, работающая по принципу LIFO (Last in – first out: последним пришел – первым вышел). Такой метод работы с памятью обеспечивает строгое соответствие прямого порядка записи данных обратному порядку их чтения. Только с помощью стека можно достаточно просто обеспечить корректное завершение работы цепочки подпрограмм, каждая из которых вызывает следующую: сначала должна быть завершена последняя, затем – предпоследняя и так далее. Максимальный размер стека – 65520 байт. Поэтому последовательность рекурсивных обращений не может быть бесконечной. В любой рекурсивной подпрограмме должна быть нерекурсивная (терминальная) ветвь, обеспечивающая выход из рекурсии. При переполнении стека работа программы прерывается, и появляется сообщение об ошибке Error 202: Stack overflow error.

Рекурсивная функция, вычисляющая факториал заданного числа n, может иметь вид:

Function Factorial(n: Word): Word;



<== предыдущая лекция | следующая лекция ==>
Подпрограммы | Процедуры


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


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

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

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


 


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

 
 

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

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