Арифметические операции

К арифметическим операциям относятся 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;
bool b2 = -b1;

В данном примере переменная b1 "расширяется" до типа int со значением 1. Обращение знака дает -1, что при обратном приведении типа к bool дает true (потому что -1 не ноль). Применение логического типа в арифметических вычислениях не приветствуется.

Деление целых чисел дает целое число, то есть дробная часть (если она возникает) отбрасывается. Проверить это можно с помощью скрипта ExprArithmetic.mq5.

int a = 24 / 7;      // ok: a = 3
int b = 24 / 8;      // ok: b = 3
double c = 24 / 7;   // ok: c = 3 (!)

Несмотря на то, что переменная c описана как double, в выражении для её инициализации стоят целые числа и потому деление выполняется целочисленное. Для того чтобы выполнялось деление с дробной частью, необходимо, чтобы хотя бы один операнд был вещественного типа (второй будет неявно преобразован также к нему).

double d = 24.0 / 7// ok: d = 3.4285714285714284

Оператор '%' вычисляет остаток от целочисленного деления (применим только к двум операндам целого типа).

int x = 11 % 5;   // ok: x = 1
int y = 11 % 5.0// нельзя использовать вещественное число
                  // error: '%' - illegal operation use

Для случаев, когда операнды имеют разные знаки, операторы '*' и '/' дают отрицательное число. Для оператора '%' действуют следующие правила:

  • когда делитель оператора '%' отрицателен, знак "уходит";
  • когда делимое оператора '%' отрицательно, результат получается отрицательным;

Это легко проверить, пользуясь альтернативным расчетом деления по модулю: m % n = m - m / n * n. Здесь следует помнить, что деление m / n для целых чисел будет с округлением, поэтому m / n * n в общем случае не равно m.

В разделе Характеристики массивов мы поднимали вопрос о том, что многомерный массив может быть представлен одномерным массивом за счет пересчета индексов элементов. Там приводилась формула для получения сквозного индекса в одномерном массиве по координатам (номеру столбца X и строки Y при длине строки N) двумерного массива.

index = Y * N + X

Операция '%' позволяет нам более удобно произвести обратный расчет, т.е. узнать X и Y по сквозному индексу:

Y = index / N
X = 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!"

Прочие операции для строк запрещены.