Содержание
Операции и выражения
Арифметические операции
Как мы уже упоминали, для каждого типа данных определены действия, применимые к его значениям. Например, если переменная относится к порядковому типу данных, то она может фигурировать в качестве аргумента стандартных функций Ord(), Pred() и Succ() (см. п. «Совместимость типов данных» ниже). А к вещественным типам эти функции применить невозможно.
Итак, поговорим теперь об операциях — стандартных действиях, разрешённых для переменных того или иного базового типа данных. Основу будут составлять арифметические операции, но, конечно же, мы не забудем и о логическом типе данных (операции, определённые для значений символьного типа, будут подробно рассмотрены в лекции 5).
Замечание: Все перечисленные ниже операции (за исключением унарных «-», «+» и not) требуют двух операндов.
- Логические операции (and, or, not, xor) применимы только к значениям типа Boolean. Их результатом также служат величины типа Boolean. Приведём таблицы значений для этих операций:
Оператор Операнд 1 Операнд 2 Результат not False - True True - False and False False False False True False True False False True True True or False False False False True True True False True True True True xor False False False False True True True False True True True False - Операции сравнения (=, <>, >, <, <=, >=) применимы ко всем базовым типам. Их результатами также являются значения типа Boolean.
- Операции целочисленной арифметики применимы, как легко догадаться, только к целым типам. Их результат — целое число, тип которого зависит от типов операндов.
a div b — деление а на b нацело (не нужно, наверное, напоминать, что деление на 0 запрещено, поэтому в таких случаях операция выдаёт ошибку). Результат будет принадлежать к типу данных, общему для тех типов, к которым принадлежат операнды. Например, (ShortInt div Byte = Integer). Пояснить это можно так: Integer — это минимальный тип, подмножествами которого являются одновременно и Byte, и ShortInt.
a mod b — взятие остатка при делении а на b нацело. Тип результата, как и в предыдущем случае, определяется типами операндов, а 0 является запрещённым значением для b. В отличие от математической операции mod, результатом которой всегда является неотрицательное число, знак результата «программистской» операции mod определяется знаком её первого операнда. Таким образом, если в математике (-2 mod 5) = 3, то у нас (-2 mod 5) = -2.
a shl k — сдвиг значения а на k битов влево (это эквивалентно умножению значения переменной а на 2k). Результат операции будет иметь тот же тип, что и первый её операнд (а).
a shr k — сдвиг значения а на k битов вправо (это эквивалентно делению значения переменной а на 2k нацело). Результат операции будет иметь тот же тип, что и первый её операнд (а).
and, or, not, xor — операции двоичной арифметики, работающие с битами двоичного представления целых чисел, по тем же правилам, что и соответствующие им логические операции.
- Операции общей арифметики (+, -, *, /) применимы ко всем арифметическим типам. Их результат принадлежит к типу данных, общему для обоих операндов (исключение составляет только операция дробного деления /, результат которой всегда относится к вещественному типу данных).
Другие операции
Помимо арифметических, существуют и другие операции, специфичные для значений некоторых стандартных типов данных языка Pascal. Эти операции мы рассмотрим в соответствующих разделах:
Стандартные арифметические функции
К арифметическим операциям примыкают и стандартные арифметические функции. Их список с кратким описанием мы приводим в таблице.
Описание | Тип аргумента | Тип результата1 | |
---|---|---|---|
Abs(x) | Абсолютное значение (модуль) числа | Арифметический | Совпадает с типом аргумента |
ArcTan(x) | Арктангенс (в радианах) | Арифметический | Вещественный |
Cos(x) | Косинус (в радианах) | Арифметический | Вещественный |
Exp(x) | Экспонента (ex) | Арифметический | Вещественный |
Frac(x) | Взятие дробной части числа | Арифметический | Вещественный |
Int(x) | Взятие целой части числа | Арифметический | Вещественный |
Ln(x) | Натуральный логарифм (по основанию e) | Арифметический | Вещественный |
Odd(x) | Проверка нечётности числа | Целый | Boolean |
Pi | Значение числа π | - | Вещественный |
Round(x) | Округление к ближайшему целому | Арифметический | Целый |
Trunc(x) | Округление «вниз» — к ближайшему меньшему целому | Арифметический | Целый |
Sin(x) | Синус (в радианах) | Арифметический | Вещественный |
Sqr(x) | Возведение в квадрат | Арифметический | Совпадает с типом аргумента |
Sqrt(x) | Извлечение квадратного корня | Арифметический | Вещественный |
Арифметические выражения
Все арифметические операции можно сочетать друг с другом — конечно, с учётом допустимых для их операндов типов данных.
В роли операндов любой операции могут выступать переменные, константы, вызовы функций или выражения, построенные на основе других операций. Всё вместе и называется выражением. Определение выражения через выражение не должно вас смущать, ведь рекурсивное задание конструкций вообще свойственно программированию (см. лекцию 9).
Примеры арифметических выражений:
(x < 0) and (y > 0) — выражение, результат которого принадлежит к типу Boolean;
z shl Abs(k) — вторым операндом является вызов стандартной функции;
(x mod k) + Min(a,b) + Trunc(z) — сочетание арифметических операций и вызовов функций;
Odd(Round(x / Abs(x))) — «многоэтажное» выражение.
Полнота вычислений
В общем случае вычисление сложного логического выражения прекращается в тот момент, когда его окончательное значение становится понятным (например, True or (b < 0)). Зачастую такой подход позволяет заметно сэкономить на выполнении «лишних» действий. Скажем, если есть некоторая сложно вычислимая функция My_Func, вызов которой входит в состав выражения
if (x <= 0) and My_Func(z + 12),
то для случая, когда x положительно, этих сложных вычислений можно избежать.
Однако включение директивы {$B+} принудит компилятор завершить эти вычисления даже в таком случае. Её выключение {$B-} вернёт обычную схему вычислений.
Порядок вычислений
Если в выражении расставлены скобки, то вычисления производятся в порядке, известном всем ещё с начальной школы: чем меньше глубина вложенности скобок, тем позже вычисляется заключённая в них операция. Если же скобок нет, то сначала вычисляются значения операций с более высоким приоритетом, затем — с менее высоким. Несколько подряд идущих операций одного приоритета вычисляются в последовательности «слева направо».
Таблица 2.1. Приоритеты (для всех) операций языка Pascal | Операции | Приоритет |
---|---|---|
Унарные2 операции | +, -, not, @, ^, # | Первый(высший) |
Операции, эквивалентные умножению | *, /, div, mod, and, shl, shr | Второй |
Операции, эквивалентные сложению | +, -, or, xor | Третий |
Операции сравнения | =, <>, >, <, <=, >=, in | Четвёртый |
Замечание: Вызов любой функции имеет более высокий приоритет, чем все внешние относительно этого вызова операции. Выражения, являющиеся аргументами вызываемой функции, вычисляются в момент вызова (см. лекцию 8).
Примеры выражений (с указанием последовательности вычислений) для целых чисел:
3 1 2
a * not b or c * d = 0 { результат принадлежит к логическому типу данных }
2 1 4 3 5
-min(a + b, 0) * (a + 1) { результат принадлежит к целочисленному типу данных }
3 2 1 5 4