Основы программирования — Осенний семестр; Михалкович С.С.; 2008; II — различия между версиями

Материал из Вики ИТ мехмата ЮФУ
Перейти к: навигация, поиск
(Подпрограммы)
(Координаты средней точки)
 
(не показаны 132 промежуточные версии 8 участников)
Строка 1: Строка 1:
==Подпрограммы==
+
[[Категория:Основы программирования]]
<small>'''Лекция 9'''</small>
+
[[Страница курса Основы программирования|К основной странице курса]]
 +
== Основные операторы ==
 +
=== Оператор присваивания := ===
 +
<xh4> Синтаксис </xh4>
 +
<переменная> ''':=''' <выражение>
  
Процедуры. Пример вычисления среднего арифметического и среднего геометрического.
+
''<u>Пример</u> использования оператора присваивания.''
 +
<source lang="Pascal">
 +
a := (3 + 5) * 8;
 +
b := a + 2;
 +
</source>
  
Синтаксис описания процедуры. Синтаксис вызова процедуры. Входные и выходные параметры.
+
<xh4> Семанитика </xh4>
 +
Вычисляется выражение в правой части, при этом, вместо имен переменных подставляются их значения. <br />
 +
Затем результат вычисления записывается в переменную в левой части.
  
Входно-выходные параметры. Процедура Swap.
+
'''Ограничение.''' Тип выражения должен быть '''''совместим по присваиванию''''' с переменной. <br />
 +
Например:
 +
* одинаковые типы совместимы.
 +
* выражение типа <tt>integer</tt> можно присвоить переменной типа <tt>real</tt>. Обратное неверно.
  
Формальные и фактические параметры. Семантические правила при вызове.
+
<xh4> Операторы присваивания += и *= </xh4>
 +
''<u>Пример</u>.''
 +
<source lang="Pascal">
 +
d += 1; //прибавить 1 к d
 +
d *= 2; //умножить d на 2
 +
</source>
  
<H3>Функции</H3>
+
<xh4> Примеры использования := </xh4>
 +
''<u>Пример 1</u>.'' Перемена местами двух значений.
 +
Дано:  <tt>x, y</tt>;
 +
<source lang="Pascal">
 +
var x, y: integer;
 +
begin
 +
  read(x,y);
 +
  var v := x;
 +
  x := y;
 +
  y := v;
 +
  writeln(x, ' ', y);
 +
end.
 +
</source>
  
Синтаксис. Вызов функции. Переменная Result.
+
Это стандартное решение.  
 +
В PascalABC.NET на основе этого алгоритма определена стандартная процедура <tt>'''Swap'''(x, y)</tt>.
  
Примеры: Sign, ReadInteger и т.п., SumN.
+
Однако, существуют и другие решения. Например:
 +
<source lang="Pascal">
 +
var x, y: integer;
 +
begin
 +
  read(x, y);
 +
  x := x + y;
 +
  y := x - y;
 +
  x := x - y;
 +
  writeln (x, ' ', y);
 +
end.
 +
</source>
  
Сравнение с процедурами на примере Sign.
+
''<u>Пример 2</u>.'' Использование промежуточных переменных в вычислениях
 +
Дано:  <tt>x: real</tt>;
 +
Найти:  <tt>x<sup>15</sup></tt>;
  
Нежелательность var-параметров в функциях.
+
<u>Решение 1</u>.
 +
<source lang="Pascal">
 +
y := x * x;
 +
z := y * y;
 +
t := z * z;
 +
p := t * z;
 +
q := p * x * y;
 +
</source>
  
Стандартные подпрограммы с передачей по ссылке: readln, Inc, Dec.
+
<u>Решение 2</u>.
 +
<source lang="Pascal">
 +
y := x * x;
 +
z := y * x;
 +
t := z * y;
 +
p := t * t * t;
 +
</source>
  
<H3>Локальные и глобальные переменные</H3>
+
<u>Решение 3</u>.
 +
<source lang="Pascal">
 +
y := x * x;
 +
x := x * y * y;
 +
t := x * x * x;
 +
</source>
  
Инициализация глобальных и локальных переменных значениями по умолчанию.
+
Заметим, что в первом решении используется 6 операций умножения, в во 2м и 3м — 5. Возникает задача: '''''найти x<sup>n</sup> за минимальное число умножений.''''' <br />
 +
Об этом читай [http://it.mmcs.sfedu.ru/forum?func=view&id=22350&catid=1 тему].
  
Понятие пространства имен.
+
=== Оператор ввода ===
 +
<xh4> Синтаксис </xh4>
 +
'''read''' (<список переменных>) | '''readln''' (<список переменных>)
  
Глобальные переменные и побочный эффект.
+
<xh4> Семантика </xh4>
 +
Происходит считывание данных с клавиатуры и запись их в переменные из <tt><списка переменных></tt>.
 +
Вводить данные нужно либо через пробел, либо по нажатию <tt><Enter></tt>, при этом программа не перейдет к выполнению следующего оператора, пока не будут считаны все данные.
  
<small>'''Лекция 10'''</small>
+
Имеются также стандартные функции ReadInteger, ReadReal, ReadlnInteger, ReadlnReal:
  
Понятие области видимости и времени жизни объекта.
+
<source lang="Delphi">var n := ReadInteger;
 +
var r := ReadlnReal;</source>
  
Изменение глобальной переменной как побочный эффект. Нежелательность такого изменения. При необходимости изменения глобальной переменной - передать ее как параметр.
+
С процедурой ввода связан ряд '''''ошибок''''' времени выполнения (например, если переменная используется в качестве делителя, и вводится 0, или, если должно быть получено целое число, а вводится <tt>'ABC'</tt>). Эти ошибки нужно уметь обрабатывать.
  
Принцип локальности: чем локальнее объявлена переменная, тем лучше. Распространение принципа локальности на внутриблочные переменнные: вспомогательные переменные, используемые в блоке алгоритма, следует делать внутриблочными.
+
=== Оператор try/except и обработка ошибок ввода ===
 +
Операторы, которые могут получать ошибку, заключаются специальный охранный блок - оператор <tt>'''try'''</tt>.
  
Понятие ссылки как другого имени объекта. Внутренний механизм передачи параметра по ссылке.
+
<xh4> Синтаксис </xh4>
 
+
<source lang="Pascal">
Перегрузка имен подпрограмм (на примере swap).
+
try
 
+
  ...
<small>'''Лекция 11'''</small>
+
  readln(a);
 
+
   ...
Параметры по умолчанию - на примере DoOp(a,b: integer; var res: integer; op: char := '+').
+
except
 
+
   <обработка ошибки>
Предварительное объявление подпрограмм.
 
 
 
==Процедурные переменные==
 
 
 
Процедурные переменные как параметры подпрограмм. Функции обратного вызова (callback).
 
 
 
Пример.
 
<source lang="delphi">
 
procedure DoActions(Act1, Act2, Act3: procedure);
 
begin
 
   Act1;
 
  Act2;
 
   Act3;
 
 
end;
 
end;
 +
<продолжение работы>
 
</source>
 
</source>
  
Пример. Вычисление определённого интеграла методом прямоугольников - Integral(a,b,N,f)
+
<xh4> Семантика </xh4>
 +
Если внутри блока '''<tt>try</tt>''' происходит ''ошибка выполнения'', то все последующие операторы в блоке игнорируются, и выполнение программы переходит к блоку '''<tt>except</tt>'''. По выходе из '''<tt>except</tt>''' программа продолжает работу.
  
Вызов нескольких действий. Операции += и -= для процедурных переменных.
+
Если ошибки не происходит, то выполняются все операторы в блоке '''<tt>try</tt>''', блок '''<tt>except</tt>''' не выполняется, и программа продолжает работу.
  
Оператор exit досрочного завершения подпрограммы
+
=== Оператор вывода ===
 +
<xh4> Синтаксис </xh4>
 +
'''write'''(<список выражений>) | '''writeln'''(<список выражений>)
  
<small>'''Лекция 12'''</small>
+
<xh4> Семантика </xh4>
==Методы разработки подпрограмм==
+
Выражения в списке вычисляются, и их значения выводятся на экран. <br />
 +
В случае <tt>writeln</tt> после вывода осуществляется переход на новую строку.
  
Метод "сверху вниз" и метод "снизу вверх" (на примере таблицы простых чисел).
+
<xh4> Форматы вывода </xh4>
 +
После каждого выражения в списке вывода можно использовать '''формат вывода''' в виде <tt>''':a'''</tt>, где <tt>'''a'''</tt> — выражение целого типа.<br />
 +
После вещественного типа — <tt>''':a:b'''</tt> (<tt>'''a'''</tt> задает ширину поля вывода (выравнивание по правому краю), <tt>'''b'''</tt> — количество знаков в дробной части).
  
Когда эффективен каждый метод:
+
<xh4> Вывод с помощью write[ln]Format </xh4>
 +
'''writelnFormat'''('<форматная строка>', <список выражений>)
  
* сверху-вниз - когда задача четко поставлена и имеется четкий алгоритм ее решения;
+
''<u>Пример</u> вывода с использованием форматной строки''.
* сниз-вверх - когда задача нечетко поставлена. когда решается группа взаимосвязанных задач из дной области, когда в задаче нет четко выделенного главного алгоритма, когда необходимо приступать к решению задачи, попутно уточняя алгоритм.
+
<source lang="Pascal">
 +
writelnFormat('{0} * {1} = {2}', a, b, a * b)
 +
</source>
  
<H3>Вызов подпрограммы на этапе выполнения</H3>
+
Будет выведено:
 +
a * b = '''a * b'''
  
Понятие программного стека.
+
В форматной строке тоже можно использовать формат вывода.
 +
<br><tt>{0, 10}</tt>: 10 — это ширина поля вывода
 +
<br><tt>{0, 10:f3}</tt>: 3 — это количество знаков в дробной части для вещественного числа (показывает это спецификатор <tt>'''f'''</tt>).
 +
<br><tt>{0, 10:e3}</tt> — экспоненциальный формат.
  
Запись активации, ее структура.
+
=== Арифметические выражения ===
 +
==== Основные сведения ====
 +
Каждое выражение имеет '''тип'''. Выражение называется '''''арифметическим''''', если его тип — ''числовой''. <br />
 +
Выражение строится посредством '''''операций''''' (унарных или бинарных) и '''''операндов'''''.
  
Алгоритм вызова подпрограммы на этапе выполнения.
+
В арифметических выражениях если <tt>a</tt> и <tt>b</tt> — одного типа, то и <tt>a '''op''' b</tt> принадлежит к тому же типу. ''Исключением'' является операция "'''/'''":
 +
:<tt>'''a / b'''</tt> — вещественное.
  
<small>'''Лекция 13'''</small>
+
Если <tt>a</tt> и <tt>b</tt> принадлежат к различным типам, то выражение принадлежит к "'''''старшему'''''" типу. <br />
 +
Например:
 +
byte < integer < int64
 +
integer < real
  
Пример, иллюстрирующий алгоритм вызова процедуры.
+
==== Стандартные функции ====
 +
В арифметические выражения могут входить стандартные функции:
 +
'''exp'''(x)
 +
'''ln'''(x)
 +
'''abs'''(x)  // модуль x
 +
'''sin'''(x)
 +
'''cos'''(x)
 +
'''sqr'''(x)  // квадрат x
 +
'''sqrt'''(x) // корень из x
 +
'''round'''(x) - целое, полученное в результате округления вещественного x
 +
'''trunc'''(x) - целое, полученное в результате отбрасывания дробной части у вещественного x
 +
'''min'''(x,y)
 +
'''max'''(x,y)
 +
'''power'''(x,y)// x в степени y
 +
'''random'''(n)// псевдослучайное целое число от 0 до n-1
 +
'''random'''(a,b)// псевдослучайное целое число от a до b
  
Замечания:
+
<xh4> Порядок выполнения операций в арифметических выражениях </xh4>
 +
* Операции с большим приоритетом выполняются первыми
 +
* Функции вычисляются до операций
 +
* Выражение в скобках вычисляется раньше
 +
* Операции с одинаковым приоритетом выполняются слева направо, если идут подряд.
  
* о накладных расходах, связанных с вызовом маленьких и больших подпрограмм
+
<xh4> Операции div и mod для целых </xh4>
* о проблеме переполнения программного стека при наличии больших локальных переменных и при передаче больших локальных переменных п значению
+
<tt>x '''div''' y = x / y, округленное до ближайшего целого по направлению к нулю.</tt> Это '''''результат''''' от ''целочисленного деления''. <br />
* о проблеме доступа к глобальным переменным
+
<tt>x '''mod''' y = x - (x div y) * y.</tt> Это '''''остаток''''' от ''целочисленного деления''.
  
==Модули==
+
''<u>Пример</u> использования'' <br />
 +
Целочисленные операции часто применяются для определения '''четности''' числа:
 +
x '''mod''' 2 = 0    <->  x — четное
 +
x '''mod''' 2 <> 0  <->  x — нечетное
  
Определение
+
=== Логические выражения ===
 +
<xh4> Основные сведения </xh4>
 +
Выражение назывется '''логическим''', если оно имеет тип <tt>'''boolean'''.</tt> <br />
 +
''<u>Пример</u>''.
 +
x < 0
 +
a >= b
 +
a <> 3
  
Структура модуля с разделами интерфейса и реализации.
+
Это простые логические выражения. Однако, с помщью '''логических операций''' можно составлять сложные.
 +
  (бинарные)    (унарные)
 +
  a '''and''' b        '''not''' a
 +
  a '''or''' b
 +
  a '''xor''' b
  
Принцип сокрытия информации.
+
<xh4> Таблицы истинности логических операций </xh4>
 +
a | b | a '''and''' b | a '''or''' b | a '''xor''' b
 +
 +
T | T |    T    |  T    |    F
 +
T | F |    F    |  T    |    T
 +
F | T |    F    |  T    |    T
 +
F | F |    F    |  F    |    F
  
Преимущества разделения модуля на интерфейс и реализацию.
+
<xh4> Сокращение вычислений логических выражений </xh4>
 +
Большинство современных компиляторов, в т.ч. PascalABC.NET производит '''''сокращенное вычисление логических выражений'''''. <br />
 +
Это означает, что в выражении
 +
a '''and''' b
 +
если a — ложно, то <tt>b</tt> не вычисляется, а в
 +
a '''or''' b
 +
если <tt>a</tt> — истинно, <tt>b</tt> не вычисляется.
  
<small>'''Лекция 14'''</small>
+
Это очень полезно при вычислении таких выражений, как, например,
 +
(y <> 0) '''and''' (x / y > 0)
  
Упрощенная структура модуля.
+
Логически здесь все верно, однако, если бы не использовалось сокращенное вычисление, в случае равенства нулю <tt>y</tt>'а возникала бы ошибка деления на ноль.
  
Разделы инициализации и финализации.
+
<xh4> Логические переменные </xh4>
 +
Можно описывать логические переменные (тип <tt>'''boolean'''</tt>). Им можно присваивать логические выражения. <br />
 +
Эти переменные принимают одно из двух возможных значений:
 +
:<tt>'''true'''</tt> (истина)
 +
:<tt>'''false'''</tt> (ложь)
  
Схема компиляции программы с модулями.
+
''<u>Пример</u> использования логических переменных'' <br />
 +
Дано: прямоугольник со сторонами, параллельными осям координат, задан координатами абсцисс вертикальных сторон (<tt>x1, x2</tt>) и ординатами горизонтальных (y1, y2); точка M( x, y ); <br />
 +
Найти: находится ли точка внутри прямоугольника, снаружи, или лежит на границе;
  
Алгоритм поиска имен в модулях. Модуль как пространство имен.
+
<source lang="Pascal">
 +
var inside, outside, bound: boolean;
 +
begin
 +
  inside := (x > x1) and (x < x2) and (y > y1) and (y < y2);
 +
  outside := (x < x1) or (x > x2) or (y < y1) or (y > y2);
 +
  bound := not inside and not outside;
 +
end.
 +
</source>
  
Системный модуль PABCSystem
+
=== Побитовые операции ===
 +
<xh4> Побитовые операции and, or, xor, not </xh4>
 +
'''Замечание.''' Работают только с целыми.
  
<small>'''Лекция 15'''</small>
+
Соответствующая операция применяется к каждому биту двоичного представления числа. <br />
 +
''<u>Пример</u>.''
 +
5 '''and''' 7
 +
5<sub>10</sub> = 101<sub>2</sub> <br />
 +
7<sub>10</sub> = 111<sub>2</sub>
  
Документирующие комментарии ///
+
101
 +
    ( '''and''' )
 +
111
 +
———
 +
101<sub>2</sub> = 5<sub>10</sub>
  
Библиотеки. Отличие библиотек от модулей. Подключение библиотек в PascalABC.NET.
+
<xh4> Операции shl и shr </xh4>
 +
'''''Побитовый сдвиг влево''''' и '''''сдвиг вправо''''' соответственно.
  
Перечислимый и диапазонный типы. Стандартные функции Ord Pred Succ. Стандартные процедуры Inc Dec.
+
<xh4> shl </xh4>
 +
x '''shl''' n = x * 2<sup>n</sup>
  
Использование перечислимого типа в for и case.
+
Сдвигает двоичное представление <tt>x</tt> на <tt>n</tt> позиций влево.
  
==Массивы==
+
<xh4> shr </xh4>
 +
x '''shr''' n = x div 2<sup>n</sup>
  
Понятие структурированного типа данных.
+
Сдвигает двоичное представление <tt>x</tt> на <tt>n</tt> позиций вправо.
  
Определение массива.
+
<xh4> Примеры </xh4>
 +
x = 5<sub>10</sub> = 101<sub>2</sub>
 +
 +
x shl 2 = <—(<sup>2</sup>)101
 +
              10100<sub>2</sub> = 20<sub>10</sub>
 +
 +
x shr 2 = 101—>(<sup>2</sup>)
 +
          001<sub>2</sub> = 1<sub>10</sub>
  
Описание массивов. Тип массива. Тип индексов массива. Понятие порядкового типа.
+
=== Таблица приоритетов операций языка Object Pascal ===
 +
# унарные <tt>'''+ - not'''</tt>
 +
# имеющие смысл ''умножения'' <tt>'''* / div mod and shl shr'''</tt>
 +
# имеющие смысл ''сложения'' <tt>'''+ - or xor'''</tt>
 +
# операции ''отношения'' <tt>'''<> <= >= < > in'''</tt>
  
<small>'''Лекция 16'''</small>
+
=== Условный оператор ===
 +
<xh4> Синтаксис </xh4>
 +
'''if''' <условие> '''then''' <оператор<sub>1</sub>>
 +
              ['''else''' <оператор<sub>2</sub>>]
  
Обращение к элементам массивов.  
+
<xh4> Семантика </xh4>
 +
[[Изображение: If.jpg]]
  
Выход за границы диапазона. Контроль выхода в Delphi и PascalABC.NET.
+
==== Примеры использования для решения задач ====
 +
''<u>Пример 1</u>.'' Нахождение минимума
 +
<br>Дано: <tt>x, y</tt>
 +
<br>Найти: <tt>min</tt>
  
Динамические массивы. Хранение в памяти.
+
<source lang="Pascal">
 +
if x > y then
 +
  min := y
 +
else
 +
  min := x;
 +
</source>
  
Инициализация массивов.
+
''<u>Пример 2</u>.'' Упорядочение <tt>a, b</tt> по возрастанию.
 
+
<br>Ясно, что если a > b, — нужно [[Основы программирования — Осенний семестр; Михалкович С.С.; 2008; II#Примеры использования := | поменять их местами]]. <br />
Присваивание массивов. Сравнение массивов.
+
Но тут одним оператором не обойтись.
 
+
Для этого можно использовать '''''составной оператор''''' — один или больше операторов, заключенных в операторные скобки <tt>'''begin'''  - '''end''';</tt>:
Присваивание a := nil для динамических массивов.
+
<source lang="Pascal">if a > b then
 
+
begin
Цикл foreach.
+
   var v := b;
 
+
   b := a;
Именная и структурная эквивалентность типов.
+
   a := v;
 
+
end;
<small>'''Лекция 17'''</small>
 
<H3>Массивы как параметры подпрограмм</H3>
 
 
 
При передаче статического массива должна соблюдаться именная эквивалентность
 
<source lang="delphi">
 
   procedure xxx(a: array [1..100] of integer); // неверно
 
 
   type IArr = array [1..100] of integer;
 
   procedure yyy(a: IArr);
 
 
</source>
 
</source>
Передавать массив по значению крайне неэффективно (т.к.происходит копирование всех элементов на стек). Его следует передавать по ссылке: для этого есть специальное ключевое слово <tt>const</tt>, которое также запрещает изменять данные внутри п/п.
 
<source lang="delphi">
 
 
  procedure zzz(const a: IArr);
 
  procedure sss(var a: IArr);
 
  
 +
''<u>Пример 3</u>.'' Вычисление функции по взаимоисключающим веткам <br />
 +
<math>y = \begin{cases} x, & x < 2 \\ x^2, & 2 < x < 3 \\ 1-x, & x \ge\; 3 \end{cases}</math>
 +
<source lang="Pascal">
 +
if x < 2 then
 +
  y := x
 +
else if x < 3 then
 +
  y := x * x
 +
else y := 1 - x;
 
</source>
 
</source>
Динамический массив
 
можно передавать в виде <tt>array of integer</tt>, т.к. для него определена структурная эквивалентность типов.
 
<source lang="delphi">
 
  procedure ttt(a: array of integer);
 
</source>
 
Передавать массив по ссылке необходимо только если внутри п/п нужно изменить длину массива.
 
Иначе можно передавать по значению, т.к. при вызове п/п на программный стек кладется только адрес участка памяти, хранящего значения элементов массива, а значит все изменения формального массива-параметра внутри п/п меняют соответствующий ему фактический параметр.
 
Массивы как возвращаемые значения функции
 
 
Часто требуется использовать массив как возвращаемое значение функции, для этого удобно использовать динамический массив, который хранит свою длину.
 
 
<h3>Переменное число параметров подпрограмм</h3>
 
 
П/п можно создавать с переменным количеством параметров.
 
Для этого исп. ключевое слово params.
 
При этом такие параметры, перечисленные через запятую, на этапе выполнения упаковываются в динамический массив, и п/п внутри работает именно с ним.
 
Пар-р params может быть только один и должен находиться последним в списке пар-ов.
 
 
<small>'''Лекция 18'''</small>
 
==Шаблоны подпрограмм==
 
 
Часто требуется выполнять одно и то же действие для разных типов данных.
 
В этом случае неудобно использовать перегрузку, т.к. п/п отличаются только заголовками.
 
 
Выход - шаблоны.
 
 
Пример:
 
 
  procedure Print<T> (array of T);
 
 
В момент вызова п/п происходит:
 
 
* выведение типов шаблона по фактическим параметрам
 
* инстанцирование - подстановка конкретных типов шаблонов и генерация кода подпрограммы с этими конкретными типами.
 
  
Если для такого типа код уже инстанцировался, то повторно действие не выполняется.
+
'''Замечание.''' Если по ветви '''<tt>else</tt>''' располагается другой оператор '''<tt>if</tt>''', то говорят, что возникает '''''цепочка вложенных операторов <tt>if</tt>'''''.
  
<H3>Задачи на одномерные массивы</H3>
+
====Координаты средней точки====
 +
''<u>Пример 4</u>.'' Даны координаты трех точек на прямой <tt>a, b, c</tt> (<tt>a, b, c</tt> попарно не равны). Найти m - координаты средней точки <br />
  
* инвертирование массива (шаблон)
+
'''Решение 1.'''
* поиск элемента в массиве - найти и вернуть индекс (шаблон)
 
  
можно с for и break,
+
Достаточно рассмотреть случай, когда координаты точек равны 1,2 и 3
  
можно и другим способом - с while
+
Рассмотрим все возможные ситуации распределения этих значений между a,b,c:
  
* поиск с барьером (шаблон). Его преимущества
+
a  b  c
* минимальный элемент массива и его индекс
+
1  2  3  a<b
* слияние двух упорядоченных массивов в один упорядоченный (барьер)
+
1  3  2  a<b
* сдвиг элементов массива влево (шаблон)
+
2  1  3
 +
2  3  1  a<b
 +
3  1  2
 +
3  2  1
  
знакомство со значением default(T), Т - тип
+
При a<b возможны три варианта, в двух из которых a<c.
 +
При a>b возможны три варианта, в двух из которых a>c.
  
<small>'''Лекция 19'''</small>
+
Решение представляется вложенными операторами if с уровнем вложенности 3.
  
<h3>Задачи на одномерные массивы</h3>
+
<source lang="Pascal">
 
+
if a < b then
pas-файл с задачами
+
  if a < c then
 
+
     if b < c then
doc-файл
+
      m := b
 
+
    else
используется тип IArr = array [1..size] of integer
+
      m := c
 
+
  else
* сдвиг элементов массива вправо (ShiftRight)
+
    m := a
 
+
else
[ два варианта определения граничных значений цикла (от n-1 до 1; от n до 2) ]
+
  if a > c then
 
+
    if b < c then
* циклический сдвиг элементов массива вправо (CycleShiftRight)
+
      m := c
* удаление элемента по заданному индексу (Delete)
+
    else
* вставка элемента по заданному индексу (Insert)
+
      m := b
 
+
   else m := a;
<H3>Задачи с процедурными переменными в качестве параметров</H3>
 
 
 
Определяется тип IUnPred = function (x: integer): boolean
 
 
 
* поиск элемента по заданному условию (Find)
 
* количество элементов, удовлетворяющих условию (Count)
 
* условный минимум (MinElem)
 
* удаление всех элементов, удовлетворяющих условию (DeleteAll)
 
 
 
'''Примечание.''' Для проверки выхода индекса за границы диапазона (внутри цикла) следует проверять граничные значения счетчика, подставляя их во все индексы
 
 
 
<small>'''Лекция 20'''</small>
 
==Сортировки==
 
 
 
* '''Выбором''' (нахождение минимального элемента в неупорядоченной части массива и перемещение его на первую после уже отсортированного участка позицию)
 
 
 
* '''Пузырьковая'''
 
 
 
Это самый компактный алгоритм сортировки. Его можно оптимизировать, проверяя случай "холостого" прохода по элементам массива. Т.е. если за проход ни один элемент не изменил позицию, значит массив уже отсортирован и проверять дальше нет смысла.
 
 
 
* '''Вставками''' (вставка элемента из еще не упорядоченного участка массива в "нужную" позицию отсортированного, для чего сдвиг части элементов вправо и вставка нового в освободившуюся позицию)
 
 
 
'''Замечание.''' Рассмотренные виды сортировки не являются самыми эффективными.
 
Асимптотическая сложность алгоритмов
 
 
 
'''Определение.''' Число шагов алгоритма асимптотически равно  Θ(f(n)) если, существуют такие N, с1, с2>0 (c1<c2), что для любых n ≥ N выполняется:
 
 
 
     c1*f(n) ≤ число шагов ≤ c2*f(n)
 
 
 
'''Замечание 1.''' Для рассмотренных алгоритмов сортировки асимптотическая сложность = Θ(n<sup>2</sup>).
 
 
 
'''Замечание 2.''' Существуют алгоритмы сортировки с асимптотической сложностью = Θ(n*logn) (они будут рассмотрены в следующем семестре).
 
 
 
<small>'''Лекция 21'''</small>
 
==Алгоритм бинарного поиска в отсортированном массиве==
 
 
 
Его асимптотическая сложность - Θ(logn).
 
Двумерные массивы
 
 
 
Двумерный массив как матрица (соответствие индексов строкам и столбцам)
 
 
 
Элементы строки. Элементы столбца (рисунки)
 
 
 
Понятие замороженного индекса
 
 
 
<H3>Задачи на двумерные массивы</H3>
 
 
 
* Вывод матрицы
 
** внешний цикл по строкам
 
** если внешним сделать цикл по столбцам будет выведена транспонированная матрица
 
 
 
* Сумма элементов в j-том столбце
 
 
 
* Сумма элементов в каждом столбце
 
** использование функции для нахождения суммы в j-ом столбце
 
* Минимальный элемент в каждой строке
 
** в отличие от предыдущей задачи, для реализации не создается дополнительная п/п.
 
 
 
'''Замечание.''' Решать такие задачи можно и реализуя алгоритм полностью,  и создавая для этого дополнительные п/п. Если задача несложная, то вполне можно пользоваться первым способом, однако если решение не очевидно, лучше выносить часть алгоритма в п/п, иначе код будет очень трудно читать.
 
 
 
* Квадратные матрицы и элементы выше-ниже главной (побочной) диагонали.
 
 
 
<small>'''Лекция 22'''</small>
 
 
 
* Поиск элемента в матрице
 
 
 
если для поиска используется функция, то при нахождении элемента выходить из циклов с помощью exit,
 
 
 
иначе удобно использовать goto КОНЕЦ_ВНЕШНЕГО_ЦИКЛА
 
 
 
==Записи==
 
 
 
<source lang="delphi">
 
type <имя записи>= record
 
   <поля записи>
 
end;
 
 
</source>
 
</source>
  
Поля записей
+
По количеству операций (3 сравнения, одно присваивание) это - самое лучшее решение
  
Инициализация записей при описании (на примере Student)
+
То же решение, записанное с помощью функции min:
  
Доступ к полям записей. Точечная нотация.
+
<source lang="Pascal">
 
+
if a < b then
'''Замечание.''' Для записей имеет место именная эквивалентность типов.
+
  if a < c then
 
+
    m := min(b,c)
Передача записей в п/п (Print(s)). Запись как возвращаемое значение функции (s := ReadStudent;).
+
  else m := a
 
+
else
Передавать записи по значению неэффективно, т.к. копируются все поля. Поэтому следуют передавать их по ссылке  (с ключевым словом const - если значения полей не изменяются, и var - если внутри п/п их требуется изменить.
+
  if a > c then
 
+
    m := min(b,c)
Оператор with.
+
  else m := a;
 
 
<source lang="delphi">
 
with <переменная типа запись> do
 
begin
 
  <поле>:=<значение>
 
end;  
 
 
</source>
 
</source>
  
Оператор удобен, когда нужно выполнить достаточное количество операций с одной и той же переменной (имя этой переменной и точка добавляются неявно перед всеми полями)
+
'''Решение 2.'''
  
<H3>Методы в записях</H3>
+
<source lang="Pascal">
 
+
var m1 := min(a,b);
На примере Student.Print.
+
var m2 := max(a,b);
 
 
Запись как пространство имен
 
 
 
Запись выступает для своих полей и методов в качестве модуля (поскольку является набором данных и связанных с ними процедур и функций, оформленных как единое целое).
 
 
 
Методы работают в некотором окружении, в роли которого выступают поля записи и другие методы.
 
 
 
Создается окружение при описании переменной типа запись.
 
 
 
* Сравнение s.Print и Print(s)
 
 
 
'''s.Print''' - объектно-ориентированный подход, доминирует объект, который сам выполняет над собой действие.
 
 
 
'''Print(s)''' - процедурно-ориентированный подход, главным является действие, выполняющееся над переменной.
 
 
 
* Метод Init - инициализатор полей записи.
 
 
 
<small>'''Лекция 23'''</small>
 
==Создание простейших графических объектов==
 
 
 
<source lang="delphi">
 
RPoint = record x, y: integer end;
 
RRectangle = record p1,p2: RPoint end;
 
 
</source>
 
</source>
  
Для каждого типа определяются методы Print, Draw, MoveOn
+
a  b  c 
 
+
1  2  3  c>m2
<H3>Записи как средство упаковки параметров</H3>
+
1  3  2 
 +
2  1  3  c>m2
 +
2  3  1  c<m1
 +
3  1  2 
 +
3  2  1  c<m1
  
'''Пример.'''
+
<source lang="Pascal">
Используем определенные типы записей для создания перегруженных версий процедур Rectangle и Line:
+
var m1 := min(a,b);
 
+
var m2 := max(a,b);
<source lang="delphi">
+
if c<m1 then
Rectangle(x1,y1, x2,y2: integer)
+
  m := m1
Rectangle(p1,p2: RPoint)
+
else if c>m2 then
Rectangle(r: RRectangle)
+
  m := m2
 
+
else m := c;
Line(x1,y1, x2,y2: integer)
 
Line(p1,p2: RPoint)
 
Line(r: RRectangle)
 
 
</source>
 
</source>
  
<H3>Переменная типа запись как объект</H3>
+
Данное решение менее эффективно по числу сравнений и присваиваний (посчитайте самостоятельно), но по понятности может восприниматься лучше предыдущего.
  
В модуле можно выносить реализацию методов записи в раздел реализации. При этом в разделе интерфейса внутри определения типа запись описываются только заголовки методов, а в разделе реализации перед именем метода необходимо писать <Имя записи>.
+
====Самостоятельные задания====
 +
* Даны координаты вершин треугольника и точка M, не лежащая на границе треугольника. Принадлежит ли M треугольнику.
 +
* Является ли 4-угольник ABCD корректно заданным.
  
Поля записи как состояние объекта.
+
=== Оператор case выбора варианта ===
 +
<xh4> Синтакстис </xh4>
 +
'''case''' <переключатель> '''of'''
 +
  {<список выбора>: <оператор>;}
 +
  ['''else''' <оператор>[;]]
 +
'''end'''
  
Методы записи как действия, воздействующие на состояние объекта.
+
<xh4> Семантика </xh4>
 +
Вначале вычисляется выражение-<tt><переключатель></tt>, после чего его значение ищется в одном из <tt><списков выбора></tt>. <br />
 +
Если значение попадает в какой-то <tt><список выбора></tt>, то выполняется соответствующий ему оператор, иначе, если есть ветвь '''<tt>else</tt>''', то выполняется оператор по ветке <tt>else</tt>.
  
Методы делятся на две категории
+
<xh4> Ограничения </xh4>
* меняющие состояние объекта (MoveOn для RPoint)
+
* выражение-переключатель должно иметь так называемый '''''порядковый''''' тип:
* осуществляющие доступ к состоянию объекта на чтение (Draw для RPoint)
+
:''целый''
 +
:''символьный''
 +
:''перечислимый''
 +
НО НЕ строковый или вещественный.
 +
* значения в <tt><списках выбора></tt> не должны пересекаться.
  
Сортировка массива записей.
+
<xh4> Примеры использования оператора выбора </xh4>
 
+
''<u>Пример 1</u>.'' День недели
<small>'''Лекция 24'''</small>
+
<source lang="Pascal">
==Индексная сортировка==
+
case DayOfWeek of
 
+
   1..5: writeln('Будний');
Часто физически переставлять элементы массива или вообще невозможно, или долго (в силу достаточно большого размера, например).
+
   6, 7: writeln('Выходный');
В этом случае удобно использовать ''перестановку индексов'' вместо перестановки самих элементов.
+
   else  writeln('Ошибка');
 
 
Идея заключается в том, чтобы описать '''индексный массив''' index, который взаимооднозначно сопоставляет ''реальным'' индексам элемента ''виртуальные'' таким образом, чтобы относительно ''виртуальных'' массив оказался упорядоченным.
 
 
 
----
 
 
 
'''Пример.'''
 
 
 
Дан массив целых (с реальными индексами):
 
  '''5'''[1]  '''15'''[2]  '''3'''[3]  '''1'''[4]  '''9'''[5]  '''8'''[6]  '''20'''[7]  '''12'''[8]
 
 
 
А так выглядит отсортированный массив по виртуальным индексам:
 
  '''1'''[1]  '''3'''[2]  '''5'''[3]  '''8'''[4]  '''9'''[5]  '''12'''[6]  '''15'''[7]  '''20'''[8]
 
 
 
Т.е.
 
  index[1] = 4
 
  index[2] = 3
 
  index[3] = 1
 
  index[4] = 6
 
  index[5] = 5
 
  index[6] = 8
 
  index[7] = 2
 
  index[8] = 7
 
 
 
----
 
Соответственно, алгоритм сортировки меняется таким образом, что вместо перемены местами самих элементов упорядочиваемого массива меняется '''содержимое элементов index'''.
 
 
 
Вначале удобно положить элементы index соответствующими '''тождественной''' подстановке (т.е. a[i] = i).
 
<source lang="delphi">
 
type CmpFunc = function (const s1,s2: Student): boolean;
 
 
 
procedure BubbleIndexStudentSort(const a: StArr; var Index: IArr; n: integer; Cmp: CmpFunc);
 
begin
 
   for var i:=1 to n do
 
    Index[i] := i;
 
   for var i:=n downto 2 do
 
  for var j:=1 to i-1 do
 
    if Cmp(a[Index[j+1]],a[Index[j]]) then
 
      Swap(Index[j+1],Index[j]);
 
end;
 
 
 
procedure WriteArrByIndex(const a: StArr; const Index: IArr; n: integer);
 
begin
 
   for var i:=1 to n do
 
    writeln(a[Index[i]].name,' ',a[Index[i]].course,' ',a[Index[i]].group);
 
 
end;
 
end;
 
</source>
 
</source>
  
==Множества==
+
''<u>Пример 2</u>.'' Цифра или буква
 
+
<source lang="Pascal">
Описание множеств. Множества-константы. Пустое множество.
+
var c: char;
 
+
read(c);
Операции над множествами:
+
case c of
s1+s2 - объединение
+
  '0'..'9': writeln('Цифра');
s1*s2 - пересечение
+
  'A'..'Z', 'a'..'z', 'а'..'я', 'А'..'Я', 'ё', 'Ё': writeln('Буква');
s1-s2 - разность
 
s += s1
 
s -= s1
 
s *= s1
 
s1<s2 - строгое вложение
 
s1<=s2 - нестрогое вложене
 
s1>s2 - строгое вложение
 
s1<=s2 - нестрогое вложене
 
i in s - принадлежность
 
 
Include(s,i);
 
Exclude(s,i);
 
Вывод множеств.
 
 
 
Цикл foreach по множеству.
 
 
 
Пример использования множеств: решето Эратосфена.
 
Алгоритм.
 
 
 
<small>'''Лекция 25'''</small>
 
<H3>Алгоритм Эратосфена</H3>
 
 
 
Код алгоритма Эратосфена
 
<source lang="delphi">
 
const n = 10000;
 
var primes: set of byte;
 
begin
 
  primes := [2..n];
 
  for var i:=2 to round(sqrt(n)) do
 
  begin
 
    if not (i in primes) then
 
      continue;
 
    var x := 2*i;
 
    while x<=n do
 
    begin
 
      Exclude(primes,x);
 
      x += i;
 
    end;
 
  end;
 
  for var i:=0 to n do
 
    if i in primes then
 
        write(i,' ');
 
end.  
 
</source>
 
 
 
<H3>Статические методы записей</H3>
 
<source lang="delphi">
 
type RRectangle = record
 
  class function EqualSquare(const r1,r2: RRectangle): boolean;
 
  class function CreateRandom: RRectangle;
 
 
end;
 
end;
 
</source>
 
</source>
 
<H3>Символы</H3>
 
 
Коды символов. Однобайтовые и двухбайтовые кодировки.
 
ASCII - стандарт на символы с кодами 0..127.
 
Unicode.
 
Однобайтовые кодировки: Windows, DOS (CP866), Koi8
 
 
Литеральные константы-символы:
 
#13 - символ возврата "каретки"
 
#10 - символ перехода на следующую строку
 
#9  - символ табуляции
 
 
<H4>Стандартные подпрограммы работы с символами</H4>
 
OrdUnicode(c)
 
ChrUnicode(i)
 
Succ(c)
 
Pred(c)
 
Inc(c,5)
 
Dec(c,5)
 
Ord(c)
 
Chr(i)
 
UpperCase(c)
 
LowerCase(c)
 
 
Для символов с кодами 0..127
 
OrdUnicode(c)=Ord(c)
 
ChrUnicode(i)=Chr(i)
 
 
char - тип, содержащий ряд статических методов:
 
 
char.IsDigit(c)
 
char.IsLetter(c)
 
char.IsLetterOrDigit(c)
 
char.IsLower(c)
 
char.IsUpper(c)
 
char.ToLower(c)
 
char.ToUpper(c)
 
 
<small>'''Лекция 26'''</small>
 
==Строки==
 
 
Тип string
 
 
Отводится память (до 2 Гб), равная длине строки, плюс некоторая дополнительная информация
 
 
Строки - массивы символов, индексируемые с 1: s[i] - i - тый символ строки.
 
var s := 'IT'; // s[1]='I', s[2]='T'
 
 
Операции со строками:
 
 
s1+s2 
 
s1 += s2 
 
s1<s2 
 
...
 
 
<H3>Основные подпрограммы работы со строками</H3>
 
 
'''Length(s)''' - функция, возвращающая длину строки s
 
 
'''SetLength(s,n)''' - процедура, устанавливающая длину строки s равной n
 
 
'''Copy(s,from,len)''' - функция, возвращающая подстроку s с позиции from длины len
 
 
'''Insert(subs,s,form)''' - процедура, вставляющая подстроку subs в строку s с позиции from
 
 
'''Delete(s,from,len)''' - процедура, удаляющая из строки s len символов с позиции from
 
 
'''Pos(subs,s)''' - функция, возвращающая позицию первого вхождения подстроки subs в строку s или 0, если подстрока не найдена
 
 
'''PosEx(subs,s,from=1)''' - функция, возвращающая позицию первого вхождения подстроки subs в строку s, начиная с позиции from, или 0, если подстрока не найдена
 
 
'''TrimLeft(s)''' - функция, возвращающая строку s, в которой удалены все начальные пробелы
 
 
'''TrimRight(s)''' - функция, возвращающая строку s, в которой удалены все заключительные пробелы
 
 
'''Trim(s)''' - функция, возвращающая строку s, в которой удалены все удаляет все начальные и заключительные пробелы
 
 
<h4>Преобразование строка <-> число</h4>
 
 
'''Str(x,s)''' - процедура, преобразующая целое или вещественное выражение x к строковому представлению и записывающая результат в строку s
 
 
'''Val(s,x,errcode)''' - процедура, преобразующая строку s к целому или вещественному значению и записывающая результат в целую или вещественную переменную x. Переменная errcode  - целая; если преобразование невозможно, то в errcode содержится номер первого символа, вызвавшего ошибку
 
 
'''IntToStr(i)''' - функция, преобразующая целое x в строку
 
 
'''StrToInt(s)''' - функция, преобразующая строку s к целому; может генерировать исключение
 
 
'''FloatToStr(i)''' - функция, преобразующая вещественное x в строку
 
 
'''StrToFloat(s)''' - функция, преобразующая строку s к вещественному; может генерировать исключение
 
 
<H3>Некоторые задачи на строки</H3>
 
 
Посимвольная обработка
 
 
* Строка 'ABCD...XYZ'
 
* Сумма всех цифр в строке s
 
 
Использование стандартных подпрограмм
 
 
* Вывести индексы всех вхождений подстроки s1 в s (на Delete, PosEx)
 
 
==Ссылки==
 
*[http://it.mmcs.sfedu.ru/wiki/index.php/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%E2%80%94_%D0%9E%D1%81%D0%B5%D0%BD%D0%BD%D0%B8%D0%B9_%D1%81%D0%B5%D0%BC%D0%B5%D1%81%D1%82%D1%80%3B_%D0%9C%D0%B8%D1%85%D0%B0%D0%BB%D0%BA%D0%BE%D0%B2%D0%B8%D1%87_%D0%A1.%D0%A1.%3B_2008 Первая часть конспекта]
 
*[[Конспекты|Другие конспекты]]
 

Текущая версия на 11:21, 14 сентября 2013

К основной странице курса

Основные операторы

Оператор присваивания :=

<xh4> Синтаксис </xh4>

<переменная> := <выражение>

Пример использования оператора присваивания.

a := (3 + 5) * 8; 
b := a + 2;

<xh4> Семанитика </xh4> Вычисляется выражение в правой части, при этом, вместо имен переменных подставляются их значения.
Затем результат вычисления записывается в переменную в левой части.

Ограничение. Тип выражения должен быть совместим по присваиванию с переменной.
Например:

  • одинаковые типы совместимы.
  • выражение типа integer можно присвоить переменной типа real. Обратное неверно.

<xh4> Операторы присваивания += и *= </xh4> Пример.

d += 1; //прибавить 1 к d
d *= 2; //умножить d на 2

<xh4> Примеры использования := </xh4> Пример 1. Перемена местами двух значений. Дано: x, y;

var x, y: integer;
begin
  read(x,y);
  var v := x;
  x := y;
  y := v;
  writeln(x, ' ', y);
end.

Это стандартное решение. В PascalABC.NET на основе этого алгоритма определена стандартная процедура Swap(x, y).

Однако, существуют и другие решения. Например:

var x, y: integer;
begin
  read(x, y);
  x := x + y;
  y := x - y;
  x := x - y;
  writeln (x, ' ', y);
end.

Пример 2. Использование промежуточных переменных в вычислениях Дано: x: real; Найти: x15;

Решение 1.

y := x * x;
z := y * y;
t := z * z;
p := t * z;
q := p * x * y;

Решение 2.

y := x * x;
z := y * x;
t := z * y;
p := t * t * t;

Решение 3.

y := x * x;
x := x * y * y;
t := x * x * x;

Заметим, что в первом решении используется 6 операций умножения, в во 2м и 3м — 5. Возникает задача: найти xn за минимальное число умножений.
Об этом читай тему.

Оператор ввода

<xh4> Синтаксис </xh4>

read (<список переменных>) | readln (<список переменных>)

<xh4> Семантика </xh4> Происходит считывание данных с клавиатуры и запись их в переменные из <списка переменных>. Вводить данные нужно либо через пробел, либо по нажатию <Enter>, при этом программа не перейдет к выполнению следующего оператора, пока не будут считаны все данные.

Имеются также стандартные функции ReadInteger, ReadReal, ReadlnInteger, ReadlnReal:

var n := ReadInteger;
var r := ReadlnReal;

С процедурой ввода связан ряд ошибок времени выполнения (например, если переменная используется в качестве делителя, и вводится 0, или, если должно быть получено целое число, а вводится 'ABC'). Эти ошибки нужно уметь обрабатывать.

Оператор try/except и обработка ошибок ввода

Операторы, которые могут получать ошибку, заключаются специальный охранный блок - оператор try.

<xh4> Синтаксис </xh4>

try
  ...
  readln(a);
  ...
except
  <обработка ошибки>
end;
<продолжение работы>

<xh4> Семантика </xh4> Если внутри блока try происходит ошибка выполнения, то все последующие операторы в блоке игнорируются, и выполнение программы переходит к блоку except. По выходе из except программа продолжает работу.

Если ошибки не происходит, то выполняются все операторы в блоке try, блок except не выполняется, и программа продолжает работу.

Оператор вывода

<xh4> Синтаксис </xh4>

write(<список выражений>) | writeln(<список выражений>)

<xh4> Семантика </xh4> Выражения в списке вычисляются, и их значения выводятся на экран.
В случае writeln после вывода осуществляется переход на новую строку.

<xh4> Форматы вывода </xh4> После каждого выражения в списке вывода можно использовать формат вывода в виде :a, где a — выражение целого типа.
После вещественного типа — :a:b (a задает ширину поля вывода (выравнивание по правому краю), b — количество знаков в дробной части).

<xh4> Вывод с помощью write[ln]Format </xh4>

writelnFormat('<форматная строка>', <список выражений>)

Пример вывода с использованием форматной строки.

writelnFormat('{0} * {1} = {2}', a, b, a * b)

Будет выведено:

a * b = a * b

В форматной строке тоже можно использовать формат вывода.
{0, 10}: 10 — это ширина поля вывода
{0, 10:f3}: 3 — это количество знаков в дробной части для вещественного числа (показывает это спецификатор f).
{0, 10:e3} — экспоненциальный формат.

Арифметические выражения

Основные сведения

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

В арифметических выражениях если a и b — одного типа, то и a op b принадлежит к тому же типу. Исключением является операция "/":

a / b — вещественное.

Если a и b принадлежат к различным типам, то выражение принадлежит к "старшему" типу.
Например:

byte < integer < int64
integer < real

Стандартные функции

В арифметические выражения могут входить стандартные функции:

exp(x)
ln(x)
abs(x)  // модуль x
sin(x)
cos(x)
sqr(x)  // квадрат x
sqrt(x) // корень из x 
round(x) - целое, полученное в результате округления вещественного x
trunc(x) - целое, полученное в результате отбрасывания дробной части у вещественного x
min(x,y) 
max(x,y) 
power(x,y)// x в степени y
random(n)// псевдослучайное целое число от 0 до n-1
random(a,b)// псевдослучайное целое число от a до b

<xh4> Порядок выполнения операций в арифметических выражениях </xh4>

  • Операции с большим приоритетом выполняются первыми
  • Функции вычисляются до операций
  • Выражение в скобках вычисляется раньше
  • Операции с одинаковым приоритетом выполняются слева направо, если идут подряд.

<xh4> Операции div и mod для целых </xh4> x div y = x / y, округленное до ближайшего целого по направлению к нулю. Это результат от целочисленного деления.
x mod y = x - (x div y) * y. Это остаток от целочисленного деления.

Пример использования
Целочисленные операции часто применяются для определения четности числа:

x mod 2 = 0    <->   x — четное
x mod 2 <> 0   <->   x — нечетное

Логические выражения

<xh4> Основные сведения </xh4> Выражение назывется логическим, если оно имеет тип boolean.
Пример.

x < 0
a >= b
a <> 3

Это простые логические выражения. Однако, с помщью логических операций можно составлять сложные.

 (бинарные)     (унарные)
  a and b         not a
  a or b
  a xor b

<xh4> Таблицы истинности логических операций </xh4>

a | b | a and b | a or b | a xor b 

T | T |    T    |   T    |    F
T | F |    F    |   T    |    T
F | T |    F    |   T    |    T
F | F |    F    |   F    |    F

<xh4> Сокращение вычислений логических выражений </xh4> Большинство современных компиляторов, в т.ч. PascalABC.NET производит сокращенное вычисление логических выражений.
Это означает, что в выражении

a and b

если a — ложно, то b не вычисляется, а в

a or b

если a — истинно, b не вычисляется.

Это очень полезно при вычислении таких выражений, как, например,

(y <> 0) and (x / y > 0)

Логически здесь все верно, однако, если бы не использовалось сокращенное вычисление, в случае равенства нулю y'а возникала бы ошибка деления на ноль.

<xh4> Логические переменные </xh4> Можно описывать логические переменные (тип boolean). Им можно присваивать логические выражения.
Эти переменные принимают одно из двух возможных значений:

true (истина)
false (ложь)

Пример использования логических переменных
Дано: прямоугольник со сторонами, параллельными осям координат, задан координатами абсцисс вертикальных сторон (x1, x2) и ординатами горизонтальных (y1, y2); точка M( x, y );
Найти: находится ли точка внутри прямоугольника, снаружи, или лежит на границе;

var inside, outside, bound: boolean;
begin
  inside := (x > x1) and (x < x2) and (y > y1) and (y < y2);
  outside := (x < x1) or (x > x2) or (y < y1) or (y > y2);
  bound := not inside and not outside;
end.

Побитовые операции

<xh4> Побитовые операции and, or, xor, not </xh4> Замечание. Работают только с целыми.

Соответствующая операция применяется к каждому биту двоичного представления числа.
Пример.

5 and 7

510 = 1012
710 = 1112

101
   ( and )
111
———
1012 = 510

<xh4> Операции shl и shr </xh4> Побитовый сдвиг влево и сдвиг вправо соответственно.

<xh4> shl </xh4>

x shl n = x * 2n

Сдвигает двоичное представление x на n позиций влево.

<xh4> shr </xh4>

x shr n = x div 2n

Сдвигает двоичное представление x на n позиций вправо.

<xh4> Примеры </xh4>

x = 510 = 1012

x shl 2 = <—(2)101
             101002 = 2010

x shr 2 = 101—>(2)
          0012 = 110

Таблица приоритетов операций языка Object Pascal

  1. унарные + - not
  2. имеющие смысл умножения * / div mod and shl shr
  3. имеющие смысл сложения + - or xor
  4. операции отношения <> <= >= < > in

Условный оператор

<xh4> Синтаксис </xh4>

if <условие> then <оператор1>
             [else <оператор2>]

<xh4> Семантика </xh4> If.jpg

Примеры использования для решения задач

Пример 1. Нахождение минимума
Дано: x, y
Найти: min

if x > y then
  min := y
else
  min := x;

Пример 2. Упорядочение a, b по возрастанию.
Ясно, что если a > b, — нужно поменять их местами.
Но тут одним оператором не обойтись. Для этого можно использовать составной оператор — один или больше операторов, заключенных в операторные скобки begin - end;:

if a > b then
begin
  var v := b;
  b := a;
  a := v;
end;

Пример 3. Вычисление функции по взаимоисключающим веткам
<math>y = \begin{cases} x, & x < 2 \\ x^2, & 2 < x < 3 \\ 1-x, & x \ge\; 3 \end{cases}</math>

if x < 2 then
  y := x
else if x < 3 then
  y := x * x
else y := 1 - x;

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

Координаты средней точки

Пример 4. Даны координаты трех точек на прямой a, b, c (a, b, c попарно не равны). Найти m - координаты средней точки

Решение 1.

Достаточно рассмотреть случай, когда координаты точек равны 1,2 и 3

Рассмотрим все возможные ситуации распределения этих значений между a,b,c:

a  b  c
1  2  3  a<b
1  3  2  a<b
2  1  3
2  3  1  a<b
3  1  2
3  2  1

При a<b возможны три варианта, в двух из которых a<c. При a>b возможны три варианта, в двух из которых a>c.

Решение представляется вложенными операторами if с уровнем вложенности 3.

if a < b then
  if a < c then
    if b < c then
      m := b
    else
      m := c
  else
    m := a
else
  if a > c then
    if b < c then
      m := c
    else
      m := b
  else m := a;

По количеству операций (3 сравнения, одно присваивание) это - самое лучшее решение

То же решение, записанное с помощью функции min:

if a < b then
  if a < c then
    m := min(b,c)
  else m := a
else
  if a > c then
    m := min(b,c)
  else m := a;

Решение 2.

var m1 := min(a,b);
var m2 := max(a,b);
a  b  c  
1  2  3  c>m2
1  3  2  
2  1  3  c>m2
2  3  1  c<m1
3  1  2  
3  2  1  c<m1
var m1 := min(a,b);
var m2 := max(a,b);
if c<m1 then
  m := m1
else if c>m2 then
  m := m2
else m := c;

Данное решение менее эффективно по числу сравнений и присваиваний (посчитайте самостоятельно), но по понятности может восприниматься лучше предыдущего.

Самостоятельные задания

  • Даны координаты вершин треугольника и точка M, не лежащая на границе треугольника. Принадлежит ли M треугольнику.
  • Является ли 4-угольник ABCD корректно заданным.

Оператор case выбора варианта

<xh4> Синтакстис </xh4>

case <переключатель> of
  {<список выбора>: <оператор>;}
  [else <оператор>[;]]
end

<xh4> Семантика </xh4> Вначале вычисляется выражение-<переключатель>, после чего его значение ищется в одном из <списков выбора>.
Если значение попадает в какой-то <список выбора>, то выполняется соответствующий ему оператор, иначе, если есть ветвь else, то выполняется оператор по ветке else.

<xh4> Ограничения </xh4>

  • выражение-переключатель должно иметь так называемый порядковый тип:
целый
символьный
перечислимый

НО НЕ строковый или вещественный.

  • значения в <списках выбора> не должны пересекаться.

<xh4> Примеры использования оператора выбора </xh4> Пример 1. День недели

case DayOfWeek of
  1..5: writeln('Будний');
  6, 7: writeln('Выходный');
  else  writeln('Ошибка');
end;

Пример 2. Цифра или буква

var c: char;
read(c);
case c of
  '0'..'9': writeln('Цифра');
  'A'..'Z', 'a'..'z', 'а'..'я', 'А'..'Я', 'ё', 'Ё': writeln('Буква');
end;