Объединение арифметических и побитовых операций с операцией присваивания

Операция Пример Эквивалент
Сложение j и k j += k j = j + k
Вычитание второго аргумента (k) из первого (j) j -= k j = j - k
Умножение j и k j *= k j = j * k
Получить частное от деления j на k j /= k j = j / k
Получить остаток от деления j на k j %= k j = j % k
Сдвиг двоичного представления j на k бит вправо j >>= k j = j >> k
Сдвиг двоичного представления j на k бит влево j <<= k j = j << k
Побитовая операция И двоичных представлений j и k j &= k j = j & k
Побитовая операция ИЛИ двоичных представлений j и k j |= k j = j | k
Побитовая операция исключающее ИЛИ двоичных представлений j и k j ^= k j = j ^ k

Приоритеты операций и порядок выполнения выражений

В прошлых выпусках я рассказал о следующих типах операций в выражении:

  • об арифметических операциях,
  • об операциях отношения,
  • о логических операциях НЕ, ИЛИ и И,
  • о побитовых операциях.

Зачастую в выражении можно встретить сразу несколько операций. Возникает вопрос - в какой последовательности эти операции будут выполняться. Это очень важный вопрос, ведь от этого зависит конечный результат, который мы в итоге получим.

Разобьем операции по группам в порядке уменьшения приоритетов.

  • 1-я группа (наивысший приоритет). Вызов функции и доступ к элементу массива (например, a[7]).
  • 2-я группа. Операции с одним операндом:
    • логическое отрицание (!);
    • побитовое отрицание (~);
    • прибавление единицы (++);
    • вычитание единицы (--);
    • изменение знака на противоположный (-).
  • 3-я группа. Побитовые операции:
    • побитовая операция И (&);
    • побитовая операция ИЛИ (|);
    • побитовая операция исключающее ИЛИ (^);
    • побитовый сдвиг вправо (>>);
    • побитовый сдвиг влево (<<).
  • 4-я группа. Ряд арифметических операций:
    • умножение (*);
    • деление (/);
    • получение остатка от деления (%).
  • 5-я группа. Оставшиеся арифметические операции:
    • сложение (+);
    • вычитание (-).
  • 6-я группа. Операции отношения:
    • больше (>);
    • больше или равно (>=);
    • меньше (<);
    • меньше или равно (<=);
    • равно (=);
    • не равно (!=).
  • 7-я группа. Логическая операция И (&&).
  • 8-я группа. Логическая операция ИЛИ (||).
  • 9-я группа. Операция присваивания и объединенные арифметические и побитовые операции с операцией присваивания:
    • операция присваивания (=);
    • сложение с присваиванием (+=);
    • вычитание с присваиванием (-=);
    • умножение с присваиванием (*=);
    • деление с присваиванием (/=);
    • остаток от деления с присваиванием (%=);
    • побитовая операция "И" с присваиванием (&=);
    • побитовая операция "ИЛИ" с присваиванием (|=);
    • побитовая операция исключающее "ИЛИ" с присваиванием (^=);
    • побитовый сдвиг влево с присваиванием (<<=);
    • побитовый сдвиг вправо с присваиванием (>>=).

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

Бывают случаи, когда Вам нужно изменить порядок выполнения операций по умолчанию. В этом случае Вы должны использовать круглые скобки () - они имеют наивысший приоритет.

Пример выражения:

a = 5 + 6 * 3; // переменной a будет присвоено значение 23

a = ( 5 + 6 ) *3; // переменной a будет присвоено значение 33

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

В этом выпуске я вернусь к рассмотрению нашего первого советника и расскажу об условном операторе if-else, который я использовал в функции init().

int init()
{
//----
if (iMA(NULL, 0, MAPeriod, 0, MODE_EMA, PRICE_CLOSE, 0) > Close[0])
CurrentState = STATE_SHORT;
else CurrentState = STATE_LONG;

MyOrderTicket = 0;
//----
return(0);
}

Формат условного оператора if-else:

if (выражение)
первый_оператор
else
второй_оператор

Принцип работы оператора: вычисляется значение выражения в скобках; если оно равно true, то выполняется "первый_оператор", в противном случае - "второй_оператор".

В нашем первом эксперте в функции init() есть такая строчка:

if (iMA(NULL, 0, MAPeriod, 0, MODE_EMA, PRICE_CLOSE, 0) > Close[0])
CurrentState = STATE_SHORT;
else CurrentState = STATE_LONG;

В этой строчке вычисляется выражение iMA(NULL, 0, MAPeriod, 0, MODE_EMA, PRICE_CLOSE, 0) > Close[0]. Забегая вперед, скажу, что в этом выражении сравнивается значение экспоненциальной скользящей средней по цене закрытия с периодом, определенным внешней переменной MAPeriod, и цена закрытия текущего бара ( Close[0] ).

Если значение скользяйшей средней больше цены закрытия, то выполняется первый оператор:

CurrentState = STATE_SHORT;

Если - меньше, то второй:

CurrentState = STATE_LONG;

Если в качестве оператора есть необходимость выполнить сразу несколько операторов, то можно использовать составной оператор, т.е. заключить в фигурные скобки необходимые нам операторы. При этом после закрывающей фигурной скобки точка с запятой уже не ставится.

Пример использования составного оператора можно найти и в нашем эксперте:

if (!IsTesting())
return(MarketInfo(s, MODE_LOTSIZE)*MarketInfo(StringSubstr(s, 0, 3)+"USD",
MODE_BID)/AccountLeverage());
else
{
p = iClose(StringSubstr(s, 0, 3)+"USD", Period(),
iBarShift(StringSubstr(s, 0, 3)+"USD", Period(), CurTime(), true));
return(MarketInfo(s, MODE_LOTSIZE)*p/AccountLeverage());
}

Если у нас нет необходимости в выполнении второго оператора (в случае, если выражение в круглых скобках не равно true), то часть else можно опустить:

if (выражение)
первый_оператор

Пример из нашего эксперта:

if (s == "CHFJPY")
{
p = iClose("USDCHF", Period(), iBarShift("USDCHF", Period(), CurTime(), true));
return(MarketInfo(s, MODE_LOTSIZE)/(AccountLeverage()*p));
}

Если несколько операторов if-else вложены друг в друга, а часть операторов имеет пропущенную часть else, то else всегда связывается с ближайшим предыдущим оператором if в том же блоке, не имеющим части else.

Обычно операторы в коде эксперта выполняются последовательно - один за другим. Однако часто требуется изменить последовательность их выполнения в зависимости от каких-то условий. В этом выпуске я рассмотрел один из способов изменения этой последовательности: условный оператор if-else.

Оператор цикла while

Обычно операторы в коде эксперта выполняются последовательно - один за другим. Однако часто требуется изменить последовательность их выполнения в зависимости от каких-то условий. В прошлом выпуске я рассмотрел один из способов изменения этой последовательности: условный оператор if-else. Применение этого оператора оправдано, когда есть необходимость выполнить две разные последовательности действий в зависимости от какого-то условия.

В этом выпуске я планирую рассказать об операторе цикла while. Уже само название говорит о том, что этот оператор применяется в тех случаях, когда нужно повторить какое-то количество раз одну и ту же последовательность операторов.

Формат оператора цикла while:

while (выражение)
оператор;

Каждый раз перед выполнением "оператора" будет проверяться значение "выражения". Если "выражение" истинно, то "оператор" будет выполнен. Далее "выражение" проверяется еще раз. Если оно опять истинно, то "оператор" будет выполнен еще раз. И так будет продолжаться до тех пор, пока "выражение" будет равно true. Как только выражение станет ложным, произойдет выход из цикла и управление будет передано оператору, следующему за циклом while.

Цикл while может быть не выполнен ни разу, если "выражение" изначально (при первой проверке) было ложным.

Если требуется, чтобы в теле цикла выполнялся не один оператор, а несколько, нужно использовать составной оператор, т.е. заключить несколько операторов в фигурные скобки {}. После закрывающей фигурной скобки } не должно стоять точки с запятой.

К сожалению, в нашем первом эксперте я не использую цикл while, поэтому пример его использования мне придется просто придумать:

int i = 0;
while ( i < 9 )
{
Print( i );
i++;
}
Print ("Done");

При первой проверке "выражение" (i<9) будет истинным (т.к. 0<9) и будет выполнен составной оператор, который состоит из функции Print (вывода информации в журнал экспертов), которая выведет число 0 в журнал, и из оператора i++, который увеличивает переменную i на единицу.

Далее выражение i<9 будет вычислено еще раз. На этот раз оно опять будет истинным. В результате в лог файл будет выведено текущее значение переменной i (т.е. 1), а после этого значение переменной будет опять увеличено на единицу и станет равным 2. Цикл будет повторяться до тех пор, пока значение переменной i не станет равным 9. Тогда выражение i<9 перестанет быть истинным и цикл прервется, а управление будет передано следующему оператору:

Print ("Done");

Оператор цикла for

В прошлом выпуске я рассказал об операторе цикла while. Этот оператор используется, когда необходимо повторить некоторую последовательность действий несколько раз (или ни одного). Подобную задачу можно решить также с помощью другого оператора цикла - оператора for.

Формат оператора цикла for:

for ( выражение1; выражение2; выражение3 )
оператор;

Выполнение оператора цикла for начинается с вычисления "выражения1". Это своего рода инициализация цикла, которая выполняется только один раз и предшествует последующим действиям.

После этого вычисляется "выражение2". Если оно истинно, то выполняется "оператор". Далее вычисляется "выражение3". Первая итерация цикла закончена. Вторая итерация начинается опять с вычисления "выражения2". Если оно истинно, то выполняется "оператор". Далее опять вычисляется "выражение3" и так продолжается до тех пор, пока "выражение2" будет истинным. Если же уже на первой итерации "выражение2" будет ложным, то цикл не исполнится ни разу.

Если вникнуть в логику работы оператора цикла for, то можно заметить, что она полностью соответствует следующему фрагменту кода с использование оператора цикла while:

выражение1;
while ( выражение2 )
{
оператор;
выражение3;
}

В прошлом выпуске мы рассмотрели пример использования оператора цикла while:

int i = 0;
while ( i < 9 )
{
Print( i );
i++;
}
Print ("Done");

Этот пример можно переписать с использованием оператора цикла for:

int i;
for (i = 0; i < 9; i++)
Print( i );
Print ("Done");

Не будет ошибкой, если любое из трех или все три выражения в операторе цикла for будут отсутствовать, однако разделяющие их точки с запятыми (;) опускать нельзя. Если отсутствует "выражение2", то принимается, что оно всегда равно true.

"Выражение1" и "выражение3" могут состоять из нескольких выражений, объединенных запятой. В этом случае вычисляется каждое из выражение, причем порядок вычисления будет слева направо:

for (i = 0, j = 0; i < 9; i++)
Print ( "i = ", i, " j= ", j );

В следующих выпусках я расскажу какими способами можно выйти из цикла (оператор break) или досрочно завершить очередную итерацию (оператор continue).

Досрочный выход из цикла с помощью оператора break

В прошлых выпусках я рассказал о двух способах организации циклов в советнике: операторе цикла while и об операторе цикла for.

Достаточно часто возникает потребность досрочно выйти из цикла - для этого используется оператор break.

Наши рекомендации