English 中文 Español Deutsch 日本語 Português
preview
От начального до среднего уровня: Операторы WHILE и DO WHILE

От начального до среднего уровня: Операторы WHILE и DO WHILE

MetaTrader 5Примеры | 31 января 2025, 15:39
334 0
CODE X
CODE X

Введение

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

В предыдущей статье От начального до среднего уровня: Оператор IF ELSE было объяснено, как изучить код для реализации управления условным потоком. Это было сделано для того, чтобы в зависимости от анализируемого выражения, мы могли выбирать, будет ли выполняться та или иная процедура.

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

Именно по этой причине языки программирования не ограничиваются дуэтом IF и ELSE. Чтобы сделать код понятней и проще, они внедряют большое количество инструкций, включая инструкции циклов.

В целом же, дорогой читатель, инструкции циклов без преувеличения являются и, возможно, еще долгое время будут, самыми опасными из существующих инструкций управления потоком. Это связано с тем, что любая небольшая ошибка во время программирования или реализации цикла может привести к катастрофе. Одна ошибка и все: ваш код войдет в бесконечный цикл, что очень опасно, и именно это чаще всего является причиной многочисленных отказов со стороны новичков. Они просто приходят в ужас, когда нужно реализовывать циклы в своих кодах.

По сути, существует два способа создания цикла в коде. Первый — использование функций и процедур вне основной процедуры, где будет реализован цикл. Второй — использование операторов управления потоком.

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

Для понимания этой статьи есть одно предварительное условие: знание концепции переменных и констант. Мы уже ранее говорили об этом. Однако, еще важнее этого знания — понимание того, как разрядность влияет на значения, и как тип переменной может влиять на ее поведение.

Если вы понятия не имеете, о чем я говорю, обратитесь к статье От начального до среднего уровня: Операторы, где я объясняю некоторые аспекты, связанные с этой темой. Несмотря на то, что там даны самые базовые сведения, их будет достаточно для того, чтобы понять мои текущие объяснения. Также не забудьте ознакомиться и с другими статьями серии для лучшего понимания всего, что будет представлено ниже.

Итак, в данный момент передо мной дилемма. Несмотря на то, что оператор FOR, фактически, является самым простым для создания циклов и, по этой причине, является любимцем программистов, у него есть определенные недостатки. Однако другие операторы, позволяющие создавать циклы, немного опаснее команды FOR. Что ж, пока я решаю, что показать первым, давайте сделаем вот что: начнем новую тему, чтобы объяснить некоторые важные вещи по этому вопросу.


Зачем использовать циклы

Многие программисты буквально паникуют при необходимости создания цикла в своем коде. Другие избегают этого всеми возможными способами и делают только тогда, когда иного выхода нет. Но чем обусловлен этот страх перед использованием циклов? Причина проста: циклы — это принимаемый риск. Каждый раз, входя в цикл, вы оказываетесь во власти собственного кода, и вам необходимо предпринять какие-то действия, чтобы завершить цикл при необходимости. Из-за того, что во многих случаях цикл может перейти в бесконечный цикл, а вы, ничего не подозревая, можете думать, что компьютер слишком долго что-то обрабатывает, когда на самом деле код застрял в бесконечном цикле.

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

Я знаю, что для многих это кажется немыслимым. Как это возможно, что программе требуются часы для выполнения задачи? Но да, дорогой читатель, бывают ситуации, когда необходимое время для выполнения задачи действительно может достигать нескольких часов. Однако в данном случае, поскольку цель носит дидактический характер, а большинство циклов, которые многие из вас создадут, будут небольшими, с величиной в тысячи итераций, обычно приложению требуется всего несколько секунд или минут для завершения. Как например, в приложениях, предназначенных для обучения нейронной сети.

В другом своем профиле я показываю, как реализовать подобную вещь: нейронную сеть, полностью написанную на чистом MQL5. На мой взгляд, такого рода приложения относятся к среднему уровню, поскольку от вас потребуются лишь хорошие знания MQL5 и соответствующего раздела математики. Остальное делается легко и просто.

Однако, я так и не ответил на вопрос вынесенный в название темы: зачем использовать циклы? Причина в простоте, которую они привносят в код. Использование циклов позволит вам контролировать, сколько раз должно быть выполнено то или иное действие, без необходимости вручную вводить команды, или использовать CTRL+C и CTRL+V для его повторения. Давайте подумаем вот о чем: в начале я показал очень простой код, целью которого было вычисление факториала любого числа. Как вы, вероятно, помните, сам код довольно прост. Для тех, кто не видел, он приведен ниже.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     uchar counter = 0;
07.     ulong value = 1;
08. 
09.     Print("Factorial of ", counter, " => ", value);
10.     counter = counter + 1;
11.     value = value * counter;
12.     Print("Factorial of ", counter, " => ", value);
13.     counter = counter + 1;
14.     value = value * counter;
15.     Print("Factorial of ", counter, " => ", value);
16.     counter = counter + 1;
17.     value = value * counter;
18.     Print("Factorial of ", counter, " => ", value);
19.     counter = counter + 1;
20.     value = value * counter;
21.     Print("Factorial of ", counter, " => ", value);
22. }
23. //+------------------------------------------------------------------+

Код 01

Код 01 может быть приемлемым для небольших чисел. Однако, по мере их увеличения, все начинает усложняться. Даже для факториала 20, настройка будет уже очень сложной, в дополнение к огромной вероятности ошибок при реализации кода, даже с использованием CTRL+C и CTRL+V. Так, в той же статье, в которой появляется этот код 01, мы разработали еще один, который можно увидеть ниже.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Factorial();
07.     Factorial();
08.     Factorial();
09.     Factorial();
10.     Factorial();
11. }
12. //+------------------------------------------------------------------+
13. void Factorial(void)
14. {
15.     static uchar counter = 0;
16.     static ulong value = 1;
17. 
18.     Print("Factorial of ", counter, " => ", value);    
19.     counter = counter + 1;
20.     value = value * counter;
21. }
22. //+------------------------------------------------------------------+

Код 02

Как вы можете заметить, теперь у нас есть немного более компактный код, что упрощает использование CTRL+C и CTRL+V для небольших факториальных вычислений. Но что, если вам нужно вычислить факториал большего числа? Как это сделать? Ну, если вы не превысите 64-битный верхний предел значения ulong, вам придется скопировать и вставить слои вычисления факториала несколько раз. И это, не считая всех усилий по корректировке кода каждый раз, когда вам нужно вычислить новый факториал. Определенно, этот трудоемкий процесс сложно назвать приятным, по этой причине использование цикла значительно упрощает обработку кода. В этом и заключается объяснение, почему следует использовать циклы.

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


Операторы WHILE и DO WHILE

Несмотря на легкую шутливость в названии темы, этот цикл очень прост для понимания, поскольку следует тем же принципам, что и оператор IF. Однако есть определенные меры предосторожности, которыми не следует пренебрегать. Это связано с тем, что при использовании этого оператора нередко совершаются ошибки. И причина проста: ЗАБЫВЧИВОСТЬ. Многие программисты забывают настроить или исправить условие, завершающее этот цикл. И как ни странно, даже очень опытные кодеры совершают эту ошибку. Итак, вот первое предупреждение: будьте осторожны при реализации кода, использующего эти операторы.

Разница между оператором WHILE и его парой DO WHILE довольно проста. WHILE иногда не выполняет внутреннюю процедуру, тогда как DO WHILE выполнит процедуру по крайней мере один раз. В принципе, это все. Просто, не правда ли? Однако, это не снижает сопутствующих рисков. Итак, начнем с самого простого оператора WHILE. Процесс его выполнения можно увидеть на изображении ниже.


Рисунок 01

Обратите внимание, это очень похоже на то, что говорилось в прошлой статье об операторе IF. Настолько, что тема, связанная с выражением, имеет здесь то же значение и принцип использования. То есть, цикл выполнит определенную в нем процедуру только в том случае, если выражение истинно. Другими словами, выражение должно быть ненулевым. Поэтому первым оператором, который я объяснил, был оператор IF. Его понимание необходимо каждому, кто хочет стать хорошим программистом, равно как и тем, кто хочет создавать программы время от времени, просто для развлечения.

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

Сначала напишем очень простой код, чтобы вы поняли, что такое цикл. Не для того, чтобы вы с ним наконец-то столкнулись, а чтобы посмотрели, как это работает на практике. Для этого, давайте проанализируем приведенный ниже код.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char info = 10;
07. 
08.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
09. 
10.     while (info)
11.     {
12.         info = info - 1;
13.         Print(__FUNCTION__, " : ", info);
14.     }
15. 
16.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
17. }
18. //+------------------------------------------------------------------+

Код 03

Код 03 очень хорошо иллюстрирует работу оператора WHILE. При его выполнении будет выведен следующий результат, показанный ниже.


Рисунок 02

Область, отмеченная на рисунке 02, — это именно та область, которая создана циклом, представляющим собой процедуру, выполнением которой управляет оператор WHILE. Теперь давайте быстро разберемся, как это произошло, и почему обратный отсчет начался с девяти и закончился нулем.

Для этого нужно взять во внимание две вещи. Во-первых, в строке шесть мы инициализировали переменную значением десять. Когда оператор WHILE проверяет выражение, которое в данном случае является значением переменной, определенной в строке шесть, и определяет, что оно  истинно, начинается цикл. Однако, и это во-вторых, перед выводом значения на терминал в строке 13, мы используем строку 12, чтобы уменьшить значение переменной info на одну единицу. Вот почему счет идет от девяти до нуля. И он заканчивается на нуле, поскольку ноль считается значением, представляющим логическое состояние false.

А что будет, если вместо вычитания единицы из переменной info в строке 12 мы увеличим ее на одну единицу? Войдет ли цикл в бесконечный цикл? Что ж, дорогой читатель, это интересный вопрос, и вы можете сами это проверить и узнать, что произойдет. Но прежде, чем мы это сделаем, давайте разберемся, почему цикл не войдет в бесконечный цикл в этом конкретном случае?

В отличие от общепринятых представлений, где мы идем от минус бесконечности к плюс бесконечности, в вычислениях все происходит не совсем так. Существует предел для любого значения, которое может выразить компьютер. Этот предел определяется разрядностью используемого типа переменной. Мы уже говорили об этом в другой статье. Именно из-за этого ограничения (и следует отметить, что есть языки, в которых этого ограничения нет, но не в нашем случае, поскольку мы работаем с языком со строгой типизацией), если значение изменяется таким образом, что в какой-то момент достигает нуля, это означает, что в какой-то момент цикл будет завершен. Неважно, сколько времени это займет, но в какой-то момент цикл завершится. Тем не менее, есть и определенные проблемы, связанные с оператором WHILE, но чтобы не путаться, мы оставим их рассмотрение на другое время. Скорее всего, я расскажу об этом в следующей статье.

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

Поскольку MQL5 — это язык, основанный на событиях, и позже мы поговорим об этом подробнее, не так уж и часто в нем создаются циклы, ожидающие наступления того или иного события. Это более характерно для таких языков, как C или C++, которые не являются событийно-управляемыми.

Таким образом, мы создаем циклы для обеспечения контролируемой паузы в приложении. Эта пауза будет активна в течение заранее определенного времени, или до тех пор, пока не произойдет предопределенное событие. Однако, это очень редко делается напрямую с помощью цикла WHILE. Это связано с тем, что данный оператор выполнит процедуру только в том случае, если выражение истинно. И во многих случаях это не совсем то, что нам нужно.

Однако, в ситуациях аварийного выхода, цикл WHILE является лучшим вариантом. Если выражение окажется ложным с самого начала, выполнения процедуры цикла WHILE не произойдет, что во многих случаях может иметь решающее значение для предотвращения нежелательных влияний на завершение цикла, основываясь на определенных критериях, которые мы увидим позже, когда будем говорить об операторе DO WHILE.

Давайте сделаем следующее: намеренно создадим цикл, который в теории может быть бесконечным. Однако добавим условие, чтобы он мог завершиться. Такой подход можно увидеть ниже.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char info = 5;
07. 
08.     Print("Press ESC to finish counting...");
09. 
10.     while (!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE))
11.     {
12.         info = info - 1;
13.         Sleep(200);
14.         Print(__FUNCTION__, " : ", info);
15.     }
16. 
17.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
18. }
19. //+------------------------------------------------------------------+

Код 04

В 10 строке кода 04 у нас есть цикл, который, теоретически, должен выполняться вечно. Однако этого не произойдет, если пользователь нажмет клавишу ESC. Обратите внимание, что это предупреждение отображается только один раз, перед началом цикла. Если пользователь пропустит это сообщение, которое будет выведено на терминал, ситуация может стать проблематичной. На терминале вы увидите нечто похожее на то, что показано ниже.


Рисунок 03

Обратите внимание на то, что в этом случае значение переменной info стало равным нулю, и, тем не менее, цикл продолжился. Это связано с тем, что выражение, определяющее момент завершения цикла, теперь привязано к условию нажатия клавиши ESC. То есть, мы ждем наступления события, чтобы код мог продолжить выполнение. Другой тест, который мы также можем провести, и который гораздо чаще встречается в кодах, написанных на MQL5, — это проверка того, был прерван код или нет. Чтобы это проверить, достаточно изменить строку 10 кода 04 на ту, что приведена ниже.

    while ((!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)) && (!IsStopped()))

Это простое изменение позволит завершить цикл в коде 04, как при нажатии клавиши ESC, так и при удалении пользователем скрипта с графика. Все довольно просто, не правда ли, дорогой читатель? Поэтому нет смысла бояться циклов. Однако, у нас все еще есть проблема, заключающаяся в том, что сообщение в строке 8 может потеряться в процессе выполнения, из-за чего пользователь может не знать, что приложение также можно закрыть, нажав клавишу ESC.

Один из способов решения этой проблемы — поместить восьмую строку внутрь цикла. Но давайте сделаем это, используя вариацию оператора WHILE  оператор DO WHILE. Для большей ясности изложения, рассмотрим это в новой теме.


Оператор DO...WHILE

И снова я не смог удержаться от шутки в названии темы. Однако эта шутка — почти буквальное описание оператора DO WHILE. Все потому, что, хоть это и один оператор, на самом деле он действует как пара, подобно паре IF ELSE. Однако, здесь все происходит немного иначе.

Думаю, вы уже поняли, что оператор WHILE, как объяснялось выше, выполнит свою процедуру хотя бы один раз только в том случае, если условие выражения является истинным. Однако, именно благодаря тому, что у нас есть элемент DO (который буквально означает:ДЕЛАЙ) перед элементом WHILE (который буквально означает: ПОКА), мы добиваемся того, что процедура внутри цикла хотя бы единожды, но будет выполнена. Такой подход очень интересен во многих сценариях и даже весьма желателен, поскольку позволяет более точно смоделировать работу определенных процедур, когда их необходимо выполнить хотя бы один раз.

Чтобы проиллюстрировать это, давайте возьмем код 04 и изменим его так, чтобы сообщение из восьмой строки появлялось время от времени. Я знаю, что мы могли бы сделать это непосредственно в самом коде 04, но давайте предположим, что этого невозможно добиться без дублирования восьмой строки. Но что наиболее важно, мы хотим, чтобы цикл выполнился хотя бы один раз, независимо от того, что произошло до его выполнения.

Таким образом, у нас есть код, показанный ниже.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char info = 10;
07. 
08.     do
09.     {
10.         if (((info / 5) * 5) == info) Print("Press ESC to finish counting...");
11.         info = info - 1;
12.         Sleep(200);
13.         Print(__FUNCTION__, " : ", info);
14.     }while (!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE));
15. 
16.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
17. }
18. //+------------------------------------------------------------------+

Код 05

При выполнении этого кода вы увидите нечто похожее на то, что показано ниже.


Изображение 04

Здесь мы имеем дело с некоторыми вещами, в определенном смысле довольно интересными для понимания. Это связано с тем, что некоторые действия в коде 05 на первый взгляд могут показаться нелогичными. Но если вы внимательно следили и добросовестно изучали опубликованные ранее статьи, вы сможете понять их относительно быстро.

Хорошо, давайте разберемся, что здесь происходит, и почему сообщение с просьбой нажать ESC теперь отображается время от времени. Как вы можете заметить, теперь проверка, следует ли продолжать выполнение процедуры внутри цикла, проводится в строке 14, а полная процедура цикла выполняется хотя бы один раз. Надеюсь, теперь понятно, почему элемент DO сосуществует в этой комбинации с элементом WHILE.

Теперь будьте внимательны к тому, что я собираюсь объяснить, поскольку это очень важно. Идея здесь та же, что и с оператором WHILE. То есть, цикл будет выполняться до тех пор, пока выражение оператора WHILE не станет ложным. Но как вы узнаете, где начинается цикл? Если вы удалите восьмую строку, вы не будете знать точно, где начинается цикл. И что еще хуже, процедура, которая должна присутствовать в цикле, и которая идет от строки 10 до строки 13 , НЕ БУДЕТ восприниматься как процедура, а скорее как обычный код.

С другой стороны, оператор WHILE, представленный в строке 14, действительно будет циклом. Однако процедура будет пустой, поскольку внутри цикла не будет выполняться никаких других команд. Он просто бы оставался там, ожидая, пока не будет нажата клавиша ESC для его завершения.

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

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char info = 10;
07. 
08. 
09.     {
10.         if (((info / 5) * 5) == info) Print("Press ESC to finish counting...");
11.         info = info - 1;
12.         Sleep(200);
13.         Print(__FUNCTION__, " : ", info);
14.     }while (!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE));
15. 
16.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
17. }
18. //+------------------------------------------------------------------+

Код 06

Как видим, из-за этого небольшого изменения в коде, которое вполне могло бы остаться незамеченным, результат совершенно другой. Чтобы было понятнее, я не буду использовать изображение, а вместо этого покажу, что происходит, с помощью анимации, приведенной ниже.


Анимация 01

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

Теперь давайте разберемся, как и почему сообщение из строки 10 выводится время от времени. Для этого необходимо понять выражение, присутствующее в операторе IF в десятой строке. Это выражение, которое человеку может показаться абсурдным, для компьютера всегда имеет смысл, когда мы используем типизированный язык, как в случае с MQL5.

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

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

Чтобы завершить эту тему, давайте посмотрим, как будет выглядеть схема выполнения потока оператором DO WHILE. Это можно увидеть ниже.


Изображение 05

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


Заключительные выводы

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

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

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     uchar counter = 0;
07.     ulong value = 1;
08. 
09.     while (counter < 5)
10.     {
11.         counter = counter + 1;
12.         value = value * counter;
13.     }
14. 
15.     Print("Factorial of ", counter, " => ", value);
16. }
17. //+------------------------------------------------------------------+

Код 07

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

Перевод с португальского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/pt/articles/15375

Прикрепленные файлы |
Anexo.zip (1.64 KB)
Добавляем пользовательскую LLM в торгового робота (Часть 5): Разработка и тестирование торговой стратегии с помощью LLM (I) - Тонкая настройка Добавляем пользовательскую LLM в торгового робота (Часть 5): Разработка и тестирование торговой стратегии с помощью LLM (I) - Тонкая настройка
Языковые модели (LLM) являются важной частью быстро развивающегося искусственного интеллекта, поэтому нам следует подумать о том, как интегрировать мощные LLM в нашу алгоритмическую торговлю. Большинству людей сложно настроить эти модели в соответствии со своими потребностями, развернуть их локально, а затем применить к алгоритмической торговле. В этой серии статей будет рассмотрен пошаговый подход к достижению этой цели.
Эволюционный торговый алгоритм обучения с подкреплением и вымиранием убыточных особей (ETARE) Эволюционный торговый алгоритм обучения с подкреплением и вымиранием убыточных особей (ETARE)
Представляем инновационный торговый алгоритм, сочетающий эволюционные алгоритмы с глубоким обучением с подкреплением для торговли на Форекс. Алгоритм использует механизм вымирания неэффективных особей, для оптимизации торговой стратегии.
Интеграция MQL5 с пакетами обработки данных (Часть 1): Расширенный анализ данных и статистическая обработка Интеграция MQL5 с пакетами обработки данных (Часть 1): Расширенный анализ данных и статистическая обработка
Интеграция обеспечивает бесперебойный рабочий процесс, при котором необработанные финансовые данные из MQL5 можно импортировать в пакеты обработки данных, такие как Jupyter Lab, для расширенного анализа, включая статистическое тестирование.
Разработка системы репликации (Часть 62): Нажатие кнопки воспроизведения в сервисе (III) Разработка системы репликации (Часть 62): Нажатие кнопки воспроизведения в сервисе (III)
В данной статье мы начнем решать проблему переизбытка тиков, которые могут влиять на работу приложения при использовании реальных данных. Данный переизбыток часто мешает правильному отсчету времени, необходимому для построения минутного бара в соответствующем окне.