Глава 3 · Выражения и операции
Операции и порядок вычисления
Числа складывают, значения сравнивают, условия объединяют, текст соединяют — и во всех этих случаях работает один и тот же набор знаков. Что именно делает знак, решают типы операндов: + складывает числа или соединяет две строки, а AND применяется к логическим значениям либо к разрядам целых чисел.
Числовые операции
Бинарные числовые операции принимают выражения слева и справа от знака. Унарный минус имеет один операнд и меняет его знак.
| Операция | Действие и результат |
|---|---|
+, -, * | Сложение, вычитание и умножение. Тип результата определяется общим числовым типом операндов. |
/ | Обычное деление. Результат DECIMAL, если участвует DECIMAL и нет DOUBLE; в остальных случаях DOUBLE. |
\, MOD | Целочисленное частное и остаток. Оба операнда должны быть INTEGER или LONG; при участии LONG результат имеет тип LONG. |
^ | Возведение в степень. Результат имеет тип DOUBLE. |
Для обычной арифметики общий тип выбирается в порядке DOUBLE, DECIMAL, LONG, INTEGER: первый присутствующий тип определяет вычисление, а при участии DOUBLE операнд DECIMAL преобразуется в DOUBLE с возможной потерей точности. MIN, MAX и CLAMP проверяют такую смесь иначе; подробности приведены в статье о преобразованиях.
PRINT 7 / 2
PRINT 7 \ 2
PRINT 7 MOD 2
Результат:
3.5
3
1
Целочисленное деление отбрасывает дробную часть частного к нулю, а знак ненулевого остатка MOD совпадает со знаком левого операнда: 7 \ -2 даёт -3, -7 MOD 2 даёт -1. Деление на ноль вызывает ошибку выполнения, а переполнение целого результата не расширяет тип автоматически.
Приоритет и группировка
В таблице операции расположены от большего приоритета к меньшему; скобки группируют выражение независимо от этой таблицы. Операции одного уровня связываются слева направо, кроме степени: 2 ^ 3 ^ 2 означает 2 ^ (3 ^ 2).
| Уровень | Операции | Расшифровка |
|---|---|---|
| 1 | ^ | Возведение в степень. |
| 2 | Унарный -, NOT | Изменение знака числа; логическое или побитовое отрицание. |
| 3 | *, /, \, MOD | Умножение, деление, целочисленное деление, остаток от деления. |
| 4 | +, -, & | Сложение чисел или соединение двух строк; вычитание; соединение текстовых представлений значений. |
| 5 | <<, >> | Побитовый сдвиг влево и вправо. |
| 6 | =, <>, <, <=, >, >= | Равно, не равно, меньше, меньше или равно, больше, больше или равно. |
| 7 | AND, ANDALSO | Логическое или побитовое И; логическое И с коротким замыканием, то есть с пропуском правого операнда при ложном левом. |
| 8 | XOR | Логическое или побитовое исключающее ИЛИ. |
| 9 | OR, ORELSE | Логическое или побитовое ИЛИ; логическое ИЛИ с коротким замыканием, то есть с пропуском правого операнда при истинном левом. |
| 10 | EQV | Логическая или побитовая эквивалентность: совпадение значений или соответствующих разрядов. |
| 11 | IMP | Логическая или побитовая импликация: ложь или нулевой разряд только при истине либо единице слева и лжи либо нуле справа. |
PRINT -2 ^ 2
PRINT 2 ^ 3 ^ 2
PRINT 7 \ -2
PRINT -7 MOD 2
Результат:
-4
512
-3
-1
В первом выражении степень вычисляется раньше изменения знака; запись (-2) ^ 2 возводит в квадрат уже отрицательное число.
Сравнение значений
Результат любого сравнения имеет тип BOOLEAN. Для чисел и строк допустимы равенство =, неравенство <> и упорядоченные сравнения <, <=, >, >=; строки сравниваются по кодовым единицам UTF-16 с различением регистра и без языковой сортировки. Для BOOLEAN поддержаны только равенство и неравенство.
Числовое сравнение использует то же продвижение типов, что сложение: если один операнд DOUBLE, другой приводится к DOUBLE, и округление при этом может повлиять на результат сравнения.
Временные значения сравниваются по правилам даты и времени, равенство пользовательских записей определяется правилами TYPE. Совпадение внешнего текстового представления само по себе не делает значения разных типов совместимыми.
Логические операции
NOT с одним операндом BOOLEAN меняет TRUE на FALSE и обратно, а бинарные операции принимают два логических выражения. Полные таблицы истинности и договор типа находятся в статье BOOLEAN.
- AND возвращает TRUE при истинности обоих операндов.
- OR возвращает TRUE, если хотя бы один операнд истинен.
- XOR возвращает TRUE, если истинен ровно один операнд.
- EQV возвращает TRUE при совпадении значений.
- IMP возвращает FALSE только для
TRUE IMP FALSE.
Эти бинарные операции вычисляют оба операнда, даже если первый уже определяет результат. Для условного вычисления правой части предусмотрены отдельные операции:
<логическое выражение> ANDALSO <логическое выражение>
<логическое выражение> ORELSE <логическое выражение>
ANDALSO пропускает правую часть при ложной левой, ORELSE — при истинной. Обе формы принимают только BOOLEAN. Так проверяют допустимость действия до его выполнения:
PRINT FALSE ANDALSO (7 / 0 > 1)
PRINT TRUE ORELSE (7 / 0 > 1)
Результат:
FALSE
TRUE
В этих выражениях деление не выполняется. Проверку делителя можно записать перед делением:
DIM divisor AS INTEGER = 0
PRINT divisor <> 0 ANDALSO 12 / divisor > 2
PRINT divisor = 0 ORELSE 12 / divisor > 2
Замена ANDALSO на AND или ORELSE на OR приводит к вычислению правой части и ошибке деления на ноль. Короткое замыкание при этом не отменяет проверку имён и типов правого операнда до запуска: FALSE ANDALSO missing всё равно отклоняется, если имя missing не объявлено.
Целочисленные разряды и сдвиги
NOT, AND, OR, XOR, EQV и IMP над INTEGER и LONG обрабатывают разряды числа и возвращают целое значение, а BOOLEAN и целые числа не смешиваются: NOT FALSE возвращает TRUE, NOT 0 возвращает -1. Ширины типов, маски и сдвиги описаны в статье побитовых операций.
Целые числа записываются десятичными, шестнадцатеричными &H и двоичными &B литералами. Префикс меняет запись числа, но не создаёт отдельный тип; правила величины и вывода приведены в статье «Системы счисления».
Соединение текста
Операция + соединяет две строки. Операция & вдобавок получает текстовое представление поддерживаемых скалярных значений: STRING, четырёх числовых типов, BOOLEAN, DATE, TIME, DATETIME и UTCDATETIME. Массивы, записи, файлы и графические ресурсы такими операндами не являются.
PRINT "Количество: " & 3
PRINT "Готово: " & TRUE
Результат:
Количество: 3
Готово: TRUE
Результат соединения ограничен предельной длиной STRING: превышение вызывает MB3007 до записи результата присваивания.
Порядок вычисления операндов при соединении
В соединении строк сначала вычисляется левый операнд, затем правый, и уже прочитанный текст слева сохраняется, даже если вызов справа изменит исходную переменную. Это действует и при записи результата в ту же переменную:
DIM text AS STRING = "А"
text = text + Change()
PRINT text
FUNCTION Change() AS STRING
text = "Х"
RETURN "Б"
END FUNCTION
Результат:
АБ
Вызов Change меняет переменную, но левый операнд сложения уже содержит прежнюю строку; затем присваивание записывает итог соединения. Для операции & действует тот же порядок.
Диагностика
MB0003: некорректный числовой литерал, например префикс &H без цифр.MB0004: величина литерала выходит за поддерживаемый диапазон.MB2003: операция применена к несовместимым типам.MB3001: деление на ноль.MB3007: соединённая строка превышает допустимую длину.MB3008: арифметическое переполнение или неконечный числовой результат.MB3012: отрицательное основание степени возводится в нецелую степень.MB3005: количество сдвига после преобразования находится вне диапазона от 0 до 63.
Запускаемые примеры
Откройте нужный файл в IDE и запустите его. Примеры с ошибкой предназначены для проверки сообщения компилятора или выполнения.