Арифметические операции
К арифметическим операциям относятся 5 бинарных: сложение, вычитание, умножение, деление и деление по модулю, а также 2 унарных: плюс и минус. В таблице приведены символы, использующиеся для каждой из этих операций.
В колонке с примерами e1, e2 — это произвольные подвыражения. Ассоциативность помечена буквами 'L' (слева направо) и 'R' (справа налево). Номер в первой колонке можно расценивать, как очередность выполнения операции.
П |
Символы |
Описание |
Пример |
А |
---|---|---|---|---|
2 |
+ |
Унарный плюс |
+e1 |
R |
2 |
- |
Унарный минус |
-e1 |
R |
3 |
* |
Умножение |
e1 * e2 |
L |
3 |
/ |
Деление |
e1 / e2 |
L |
3 |
% |
Деление по модулю |
e1 % e2 |
L |
4 |
+ |
Сложение |
e1 + e2 |
L |
4 |
- |
Вычитание |
e1 - e2 |
L |
Порядок в таблице соответствует понижению приоритетов: унарные плюс и минус вычисляются раньше, чем умножение и деление, а те, в свою очередь — раньше, чем сложение и вычитание.
double a = 3 + 4 * 5; // a = 23 |
Унарный плюс фактически не имеет эффекта при вычислениях, но может использоваться для большей наглядности выражения. Унарный минус меняет знак своего операнда на противоположный.
Арифметические операции применяются к числовым типам или приводимым к ним. Результат вычисления является RValue. В процессе вычислений часто производится расширение разрядности целочисленных операндов до наиболее "большого" из использованных целых или int (если все целые типы были меньшего размера), а также приведение к общему типу. Подробнее об этом — в разделе Приведение типов.
bool b1 = true;
|
В данном примере переменная b1 "расширяется" до типа int со значением 1. Обращение знака дает -1, что при обратном приведении типа к bool дает true (потому что -1 не ноль). Применение логического типа в арифметических вычислениях не приветствуется.
Деление целых чисел дает целое число, то есть дробная часть (если она возникает) отбрасывается. Проверить это можно с помощью скрипта ExprArithmetic.mq5.
int a = 24 / 7; // ok: a = 3
|
Несмотря на то, что переменная c описана как double, в выражении для её инициализации стоят целые числа и потому деление выполняется целочисленное. Для того чтобы выполнялось деление с дробной частью, необходимо, чтобы хотя бы один операнд был вещественного типа (второй будет неявно преобразован также к нему).
double d = 24.0 / 7; // ok: d = 3.4285714285714284 |
Оператор '%' вычисляет остаток от целочисленного деления (применим только к двум операндам целого типа).
int x = 11 % 5; // ok: x = 1
|
Для случаев, когда операнды имеют разные знаки, операторы '*' и '/' дают отрицательное число. Для оператора '%' действуют следующие правила:
- когда делитель оператора '%' отрицателен, знак "уходит";
- когда делимое оператора '%' отрицательно, результат получается отрицательным;
Это легко проверить, пользуясь альтернативным расчетом деления по модулю: m % n = m - m / n * n. Здесь следует помнить, что деление m / n для целых чисел будет с округлением, поэтому m / n * n в общем случае не равно m.
В разделе Характеристики массивов мы поднимали вопрос о том, что многомерный массив может быть представлен одномерным массивом за счет пересчета индексов элементов. Там приводилась формула для получения сквозного индекса в одномерном массиве по координатам (номеру столбца X и строки Y при длине строки N) двумерного массива.
index = Y * N + X |
Операция '%' позволяет нам более удобно произвести обратный расчет, т.е. узнать X и Y по сквозному индексу:
Y = index / N
|
Если в процессе вычисления выражения на каком-то этапе получился непредставимый результат NaN (Not A Number, например, бесконечность, корень из отрицательного числа и т.д.), все последующие операции с ним также дают NaN. Отличить его от нормального числа можно с помощью функции MathIsValidNumber (см. Математические функции).
double z = DBL_MAX / DBL_MIN - 1; // inf: Not A Number |
Тут вычитание уже производится из NaN (полученного при делении) и дает в результате тоже NaN.
Операция сложения определена для строк и выполняет конкатенацию, то есть их объединение.
string s = "Hello, " + "world!"; // "Hello, World!" |
Прочие операции для строк запрещены.