Условные операторы Pascal-Паскаль
Условные операторы позволяют выбирать для выполнения те или иные части программы в зависимости от некоторых условий. Если, например, в программе используются вещественные переменные x и z, и на каком-то этапе решения задачи требуется вычислить z=max(x, y), то желаемый результат получается в результате выполнения либо оператора присваивания z:=x, либо оператора присваивания z:=y. Поскольку значения переменных x и y заранее неизвестны, а определяются в процессе вычислений, то в программе необходимо предусмотреть оба эти оператора присваивания. Однако на самом деле должен выполниться один из них. Поэтому в программе должно содержаться указание о том, в каком случае надо выбирать для исполнения тот или иной оператор присваивания.
Это указание естественно сформулировать с использованием отношения x>y. Если это отношение при текущих значениях x и y справедливо (принимает значение true), то для исполнения должен выбираться оператор z:=x; в противном случае для исполнения должен выбираться оператор z:=y (при x=y безразлично, какой оператор выполнять, так что выполнение оператора z:=y в этом случае даст правильный результат).
Для задания подобного рода разветвляющихся вычислительных процессов в языках программирования существуют условные операторы. Рассмотрим полный условный оператор Паскаля:
if B then S1 else S2
Здесь if (если), then (то) и else (иначе) являются служебными словами,В – логическое выражение, а S1 и S2 – операторы.
Выполнение такого условного оператора в Паскале сводится к выполнению одного из входящих в него операторов S1 или S2: если заданное в операторе условие выполняется (логическое выражение В принимает значение true), то выполняется оператор S1, в противном случае выполняется оператор S2.
Алгоритм решения упомянутой выше задачи вычисления z= max( x, y) можно задать в виде условного оператора Паскаля
if x>y then z:= x else z:= y
При формулировании алгоритмов весьма типичной является такая ситуация, когда на определенном этапе вычислительного процесса какие-либо действия надо выполнить только при выполнении некоторого условия, а если это условие не выполняется, то на данном этапе вообще не нужно выполнять никаких действий. Простейшим примером такой ситуации является замена текущего значения переменной х на абсолютную величину этого значения: если x<0, то необходимо выполнить оператор присваивания x:= - x; если же x>=0, то текущее значение х должно остаться без изменений, т.е. на данном этапе вообще не надо выполнять каких-либо действий.
В подобных ситуациях удобна сокращенная форма записи условного оператора в Паскале:
if B then S
Правило выполнения сокращенного условного оператора Паскаля достаточно очевидно: если значение логического выражения В есть true, то выполняется оператор S; в противном случае никаких иных действий не производится.
В языке программирования Паскаль в условном операторе между then и else, а также после else по синтаксису может стоять только один оператор. Если же при выполнении (или невыполнении) заданного условия надо выполнить некоторую последовательность действий, то их надо объединить в единый, составной оператор, т.е. заключить эту последовательность действий в операторные скобки begin... end (это важно!). Если, например, при x< y надо поменять местами значения этих переменных, то условный оператор будет записан следующим образом в Паскале:
if x<y then begin r:=x; x:=y; y:=r end
Наличие сокращенной формы условного оператора Паскаля требует большой осторожности при использовании. Например, условный оператор
if B1 then if B2 then S1 else S2
допускает, вообще говоря, две разные трактовки:
- как полный условный оператор Паскаля вида
ifB1 then begin
if B2 then S1 end
else S2
- как сокращенный условный оператор Паскаля вида
if B1 then begin
if B2 then S1 else S2 end
По правилам Паскаля имеет место вторая трактовка, т.е. считается, что каждое слово else соответствует первому предшествующему ему слову then. Для избежания возможных ошибок и недоразумений можно порекомендовать во всех подобных случаях четко выделять желаемую форму условного оператора Паскаля путем взятия в операторные скобки.
9.
Содержимое внутренней памяти ЭВМ разделяется на команды и данные. Команды определяют что именно им делать. Когда команда считывается из памяти (внутренней) она поступает в устройство управления. Устройство управления анализирует команду, определяет необходимые действия и выполняет их (считает данные из памяти в АЛУ, выполняет над ними определенные операции и записывает результаты обратно в память). В общем случае можно сказать, что существует четырех- , трех-, двух-, одно- и безадресные команды. Такие команды имеют вид:
Код операции | Адрес 1 | Адрес 2 | Адрес 3 | Адрес 4 |
Код операции | Адрес 1 | Адрес 2 | Адрес 3 | |
Код операции | Адрес 1 | Адрес 2 | ||
Код операции | Адрес | |||
Код операции | ||||
Код операции | регистры |
Код операции определяет то действие, которое должна выполнить команда. Адрес 1 и адрес 2 определяют адреса ячеек памяти исходных данных. Адрес 3 определяет ячейку памяти, куда помещается результат. Адрес 4 определяет откуда выбирается следующая команда.
Рассмотрим процесс выполнения четырехадресной команды по шагам. Считаем, что подлежащая выполнению команда находится в регистре команд.
1. Команда поступает на дешифрирующее устройство и определяется её код операции и адреса, где находится данные.
2. Исполнительное устройство считывает первый операнд из ячейки памяти с адресом адрес 1 регистр 1 данных.
3. Исполнительное устройство считывает второй операнд из ячейки памяти с адресом адрес 2 регистр 2 данных.
4. Арифметико-логическое устройство выполняет необходимую операцию, результат сохраняется в регистре результата регистра состояния.
5. Содержимое регистра результата пересылается в ячейку памяти с адресом 3.
6. Команды из ячейки памяти с адресом 4 считывается в регистр команд.
В случае трехадресной команды отсутствует адрес 4 т.е. адрес следующей команды, поэтому вводятся дополнительные регистры – указатели команд, в которых содержатся адреса следующих команд. В процессе выполнения меняется только шаг 6, в котором регистр команд считывает команды из ячейки памяти, адрес которой содержится в указателе команд и добавляется шаг 7, в котором значения указателя команд увеличиваются на 1.
Двух адресная( одно-, без-) используется вместе. Двухадресные команды содержат только либо адрес операндов, либо адрес одного из операндов и результат.
Одноадресная команда либо загружает один операнд, либо сохраняет результат.
Безадресная команда работает с данными заранее загруженными в регистре.
10.
Тема: Понятие рекурсии.
Рекурсия (от латинского recursio - возвращение) - это такой способ организации вычислительного процесса, при котором процедура или функция в ходе выполнения составляющих ее операторов обращается сама к себе.
Для того, чтобы такое обращение не было бесконечным, в тексте подпрограммы должно быть условие, по достижению которого дальнейшего обращения не происходит. таким образом, рекурсивное обращение может включаться только в одну из ветвей подпрограммы.
В языке Паскаль нет никаких ограничений на рекурсивные вызовы подпрограмм, необходимо только понимать, что каждый очередной рекурсивный вызов приводит к образованию новой копии локальных объектов подпрограммы и все эти копии, соответствующие цепочке активизированных и не завершенных рекурсивных вызовов, существуют независимо друг от друга
Рекурсия достаточно широко применяется в программировании, что основано на рекурсивной природе многих математических алгоритмов. А также Вы должны знать, что любой рекурсивный алгоритм можно преобразовать в эквивалентный итеративный (то есть использующий циклические конструкции).
В больших и сложных программах иногда приходится заменять рекурсию на итерацию. Дело в том, что рекурсия связана с многократными вызовами процедур, а это несколько менее эффективно при выполнении по сравнению с использованием циклов. Однако рекурсивные версии программ, как правило, гораздо короче и нагляднее.
Хорошей иллюстрацией механизма рекурсии является функция для вычисления факториала натурального числа. Вспомним, что факториалом числа называется произведение всех натуральных чисел от 1 до этого числа включительно:
N! = 1*2*3* . . . *(N-2)*(N-1)*N
1! = 1
0! = 1
Сначала покажем обычную не рекурсивную функцию для вычисления факториала, которая реализует итеративный алгоритм вычисления:
Function NonRecFact(N:integer) : LongInt; Var i : integer; {переменная цикла } Res : LongInt; {результат} Begin Res := 1; for i := 1 to N do res := Res*i; NonResFact := Res; End; |
Вторая функция использует рекурсивные обращения, что делает ее гораздо компактнее, и основана на очевидном соотношении:
N! = (N-1)!*N
Иными словами, чтобы получить значение факториала от числа N, достаточно умножить на N значение факториала от предыдущего числа:
Function RecFact(N:integer) : LongInt; Begin if N <= 1 then ResFact := 1 else ResFact := N*ResFact(N-1); End; |
Полностью программа, вычисляющая факториал числа, будет выглядеть так:
Program Rekurs; Var N : integer; F : Longint; Function RecFact(N:integer) : LongInt; Begin if N <= 1 then ResFact := 1 else ResFact := N*ResFact(N-1); End; Begin writeln('Введите число N > '; read(N); F := RecFact(N); writeln('Для числа ',N,' значение факториала равно ',F); End. |
После запуска программы на экран выводится запрос "Введите число N > ", затем с клавиатуры считывается введенное значение и в выражении F:=RecFact(N) вызывается функция RecFact с параметром-значением N. В подпрограмме-функции проверяется условие N<=1. Если оно выполняется, то функции ResFact присваивается значение 1 и на этом выполнение подпрограммы завершается. Если условие N<=1 не соблюдается, то выполняется вычисление произведения N*ResFact(N-1).
Вычисление произведения носит рекурсивный характер, так как при этом осуществляется вызов функции ResFact(N-1), значение которой вычисляется, в свою очередь, через вызов функции ResFact, параметром которой также будет функция ResFact, и т.д., до тех пор пока значение формального параметра N не будет равно 1. Так как базовая часть описания рекурсивной функции ResFact определяет значение ResFact для N=1, равным единице, то рекурсивные вызовы функции ResFact больше не выполняются, а наоборот выполняется вычисление функции ResFact для чисел, возрастающих от 1 до N , причем функция ResFact всякий раз возвращает значение, равное произведению очередного числа на факториал от предыдущего числа. Последнее возвращение результата вычисления функции ResFact присвоит переменной F значение произведения всех чисел от 1 до N, т.е. факториал числа N.
Итак, при выполнении рекурсивной подпрограммы осуществляется многократный переход от некоторого текущего уровня организации алгоритма к нижнему уровню последовательно до тех пор, пока не будет получено тривиальное решение поставленной задачи. В нашем примере решение при N=1 тривиально, т.е. ResFact=1. Затем осуществляется возврат на верхний уровень с последовательным вычислением значения функции ResFact.