サイクル演算子 'while'
MQL4の最も強力な機能は、サイクル(ループ)を整理することです。
アプリケーションプログラムを作成するときは、多くの場合繰り返しプログラム行である繰り返し計算を使用することがあります。 プログラミングを快適にし、プログラム自体をユーザーフレンドリーにするために、我々はサイクル演算子を使用する。 MQL4には、whileとforの2つのサイクル演算子があります。 このセクションの最初のものを検討します。
演算子 'while'の書式
フルフォーマットのサイクル演算子 'while'は、条件を含むヘッダーと、実行可能なサイクル本体を中括弧で囲みます。
1 2 3 4 5 |
<span class="notranslate"> <b>while(</b>条件<b>)</b></span> <b> </b> <span class="notranslate"> //サイクル演算子のヘッダー</span> <span class="notranslate"> <b>{</b> //オープニングブレース</span> <span class="notranslate">演算子のブロック//サイクル演算子の本体は、次のようになります。</span> <span class="notranslate">いくつかの演算子のサイクル本文を構成する//</span> <span class="notranslate"> <b>}</b> //中括弧を閉じる</span> |
サイクル本体が演算子 'while'に1つだけの演算子で構成されている場合、中括弧は省略できます。
1 2 |
<span class="notranslate"> <b>while(</b>条件<b>)</b></span> <b> </b> <span class="notranslate"> //サイクル演算子のヘッダー</span> <span class="notranslate"> 1つの演算子、サイクル本体//サイクル本体は1つの演算子</span> |
オペレーターの実行ルール 'while'
演算子 'while'の条件が真である限り、プログラムは制御をサイクル本体のオペレータに渡します。 サイクル本体内のすべての演算子が実行された後、条件の真偽をテストするためにコントロールをヘッダーに渡します。 演算子 'while'の条件が偽である場合、制御は、演算子 'while'に続く演算子に渡されなければなりません。 |
例を考えてみましょう。
問題12フィボナッチ係数を10の有効数字の精度で計算する。 |
まず、簡単にフィボナッチ係数を説明しましょう。 イタリアの数学者、Leonardo Fibonacciは、数列のユニークな配列を発見しました。
1 1 2 3 5 8 13 21 34 55 89 144 233 ...
このシーケンスの各数字は、先行する2つの数字の合計です。 この数列にはいくつかの固有の特性があります。シーケンス内の2つの連続する数の比は1.618に等しく、前の数との比は0.618になります。 比1.618はフィボナッチにちなんで命名され、上記の配列はフィボナッチ配列と命名された(フィボナッチ数の共役である0.3819は、それ自体を掛けることによって得られたことにも注意すべきである:0.3819 = 0.618×0.618)。
課題は、フィボナッチ数をより正確に計算することです。 フィボナッチ数列の数十の要素についてフィボナッチ係数を分析すると、得られた係数は、1.61803398875 ...の非合理的な数の範囲にわたることが明らかになります。 より大きな数の配列が計算に関与しているほど、この値からの結果の偏差が小さくなります。
10番目の重要な数字の後にのみ、係数が互いに異なる正確な数字を事前に知ることはできません。 したがって、係数の差が0.0000000001未満になるまで係数を連続して検索するプログラムを作成する必要があります。
この例では、問題12を解決するためのスクリプト( fibonacci.mq4 )を作成しました。これは、プログラムがすべての目盛りを確認するために長い間使用されないためです。 シンボルウィンドウに接続すると、スクリプトは必要な計算(表示された結果を含む)をすべて実行してから、クライアント端末によってウィンドウからアンロードされます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<span class="notranslate"> <span class="hl-comment">// ------------------------------------------------ ----------------------------------------</span></span> <span class="notranslate"> <span class="hl-comment">// fibonacci.mq4</span></span> <span class="notranslate"> <span class="hl-comment">//</span> <span class="hl-comment">コードは教育目的でのみ使用する必要があり</span> <span class="hl-comment">ます。</span></span> <span class="notranslate"> <span class="hl-comment">// ------------------------------------------------ ----------------------------------------</span></span> <span class="notranslate"> <span class="hl-reserved">int</span> <span class="hl-identifier">start</span> <span class="hl-brackets">()</span> <span class="hl-comment">//特殊な関数start()</span></span> <span class="notranslate"> <span class="hl-brackets">{</span></span> <span class="notranslate"> <span class="hl-comment">// ------------------------------------------------ ----------------------------------------</span></span> <span class="notranslate"> <span class="hl-reserved">int</span> <span class="hl-identifier">i</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//形式パラメータ、カウンタ</span></span> <span class="notranslate"> <span class="hl-reserved">ダブル</span></span> <span class="notranslate"> <span class="hl-identifier">A</span> <span class="hl-code">、</span> <span class="hl-identifier">B</span> <span class="hl-code">、</span> <span class="hl-identifier">C</span> <span class="hl-code">、</span> <span class="hl-comment">//シーケンス内の数字</span></span> <span class="notranslate"> <span class="hl-identifier">デルタ</span> <span class="hl-code">、</span> <span class="hl-comment">//係数間の実際の差</span></span> <span class="notranslate"> <span class="hl-identifier">D</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//プリセット精度</span></span> <span class="notranslate"> <span class="hl-comment">// ------------------------------------------------ ----------------------------------------</span></span> <span class="notranslate"> <span class="hl-identifier">A</span> <span class="hl-code">=</span> <span class="hl-number">1</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">// 初期値</span></span> <span class="notranslate"> <span class="hl-identifier">B</span> <span class="hl-code">=</span> <span class="hl-number">1</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//</span> <span class="hl-comment">初期値</span></span> <span class="notranslate"> <span class="hl-identifier">C</span> <span class="hl-code">=</span> <span class="hl-number">2</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//</span> <span class="hl-comment">初期値</span></span> <span class="notranslate"> <span class="hl-identifier">D</span> <span class="hl-code">=</span> <span class="hl-number">0.0000000001</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//精度を設定する</span></span> <span class="notranslate"> <span class="hl-identifier">デルタ</span> <span class="hl-code">=</span> <span class="hl-number">1000.0</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//</span> <span class="hl-comment">初期値</span></span> <span class="notranslate"> <span class="hl-comment">// ------------------------------------------------ ----------------------------------------</span></span> <span class="notranslate"> <span class="hl-reserved">while</span> <span class="hl-brackets">(</span> <span class="hl-identifier">Delta</span> <span class="hl-code">></span> <span class="hl-identifier">D</span> <span class="hl-brackets">)</span> <span class="hl-comment">//サイクル演算子ヘッダー</span></span> <span class="notranslate"> <span class="hl-brackets">{</span> <span class="hl-comment">//サイクルボディのオープニングブレース</span></span> <span class="notranslate"> <span class="hl-identifier">私は</span> <span class="hl-code">+ +;</span></span> <span class="notranslate"> <span class="hl-comment">//カウンター</span></span> <span class="notranslate"> <span class="hl-identifier">A</span> <span class="hl-code">=</span> <span class="hl-identifier">B</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//次の値</span></span> <span class="notranslate"> <span class="hl-identifier">B</span> <span class="hl-code">=</span> <span class="hl-identifier">C</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//</span> <span class="hl-comment">次の値</span></span> <span class="notranslate"> <span class="hl-identifier">C</span> <span class="hl-code">=</span> <span class="hl-identifier">A</span> <span class="hl-code">+</span> <span class="hl-identifier">B</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//</span> <span class="hl-comment">次の値</span></span> <span class="notranslate"> <span class="hl-identifier">デルタ</span> <span class="hl-code">=</span> <span class="hl-predfunc">MathAbs</span> <span class="hl-brackets">(</span> <span class="hl-identifier">C</span> <span class="hl-code">/</span> <span class="hl-identifier">B</span> <span class="hl-code">-</span> <span class="hl-identifier">B</span> <span class="hl-code">/</span> <span class="hl-identifier">A</span> <span class="hl-brackets">)</span> <span class="hl-code">。</span></span> <span class="notranslate"> <span class="hl-comment">//係数の差を検索する</span></span> <span class="notranslate"> <span class="hl-brackets">}</span> <span class="hl-comment">//サイクルボディのブレースを閉じる</span></span> <span class="notranslate"> <span class="hl-comment">// ------------------------------------------------ ----------------------------------------</span></span> <span class="notranslate"> <span class="hl-predfunc">警告</span> <span class="hl-brackets">(</span> <span class="hl-quotes">"</span> <span class="hl-string">C =</span> <span class="hl-quotes">"</span> <span class="hl-code">、</span> <span class="hl-identifier">C</span> <span class="hl-code">、</span> <span class="hl-quotes">"</span> <span class="hl-string">フィボナッチ数=</span> <span class="hl-quotes">"</span> <span class="hl-code">、</span> <span class="hl-identifier">C</span> <span class="hl-code">/</span> <span class="hl-identifier">B</span> <span class="hl-code">、</span> <span class="hl-quotes">"</span> <span class="hl-string">i =</span> <span class="hl-quotes">"</span> <span class="hl-code">、</span> <span class="hl-identifier">i</span> <span class="hl-brackets">)</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//画面に表示する</span></span> <span class="notranslate"> <span class="hl-reserved">return</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">// Exit start()</span></span> <span class="notranslate"> <span class="hl-brackets">}</span></span> <span class="notranslate"> <span class="hl-comment">// ------------------------------------------------ ----------------------------------------</span></span> |
プログラムの初めに、変数が宣言されています(記述されています)。 それ以降の行では、変数に数値が割り当てられます。 A、B、Cはフィボナッチシーケンスの最初の数字の値を取る。 シーケンス自体には整数のみが含まれていますが、その除算の商はプログラム内で実数として考慮する必要があります。 ここでこれらの数値にint型を使用した場合、フィボナッチ係数を計算することは不可能です。たとえば、8/5 = 1(整数1、小数部なし)です。 したがって、この場合、 double型の変数を使用します。 サイクル演算子は次のようになります。
1 2 3 4 5 6 7 8 |
<span class="notranslate"> <span class="hl-reserved">while</span> <span class="hl-brackets">(</span> <span class="hl-identifier">Delta</span> <span class="hl-code">></span> <span class="hl-identifier">D</span> <span class="hl-brackets">)</span> <span class="hl-comment">//サイクル演算子ヘッダー</span></span> <span class="notranslate"> <span class="hl-brackets">{</span> <span class="hl-comment">//サイクルボディのオープニングブレース</span></span> <span class="notranslate"> <span class="hl-identifier">私は</span> <span class="hl-code">+ +;</span></span> <span class="notranslate"> <span class="hl-comment">//カウンター</span></span> <span class="notranslate"> <span class="hl-identifier">A</span> <span class="hl-code">=</span> <span class="hl-identifier">B</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//次の値</span></span> <span class="notranslate"> <span class="hl-identifier">B</span> <span class="hl-code">=</span> <span class="hl-identifier">C</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//次の値</span></span> <span class="notranslate"> <span class="hl-identifier">C</span> <span class="hl-code">=</span> <span class="hl-identifier">A</span> <span class="hl-code">+</span> <span class="hl-identifier">B</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//次の値</span></span> <span class="notranslate"> <span class="hl-identifier">デルタ</span> <span class="hl-code">=</span> <span class="hl-predfunc">MathAbs</span> <span class="hl-brackets">(</span> <span class="hl-identifier">C</span> <span class="hl-code">/</span> <span class="hl-identifier">B</span> <span class="hl-code">-</span> <span class="hl-identifier">B</span> <span class="hl-code">/</span> <span class="hl-identifier">A</span> <span class="hl-brackets">)</span> <span class="hl-code">。</span></span> <span class="notranslate"> <span class="hl-comment">//係数の差を検索する</span></span> <span class="notranslate"> <span class="hl-brackets">}</span> <span class="hl-comment">//サイクルボディのブレースを閉じる</span></span> |
サイクル演算子 'while'のブロック図を考えてみましょう。
イチジク。 42.プログラムfibonacci.mq4の演算子 - 'while'実行のブロック図。
サイクルオペレータは、条件のテストを開始します。 サイクルは、条件(デルタ> D)が真になるまで繰り返し実行されます。 演算子を読みながらキーフレーズ(実行ルール)を声を掛けて言うと、プログラムコードがはるかによく理解できます。 たとえば、演算子 'while'を読み込んだ場合、次のようになります 。 この場合、演算子 'while'のヘッダーは次のようになります。デルタがDより大きい場合は、以下を実行します。次に、サイクルボディを構成するプログラム行の解析に進み、この条件本当です。
上記のfibonacci.mq4の例の制御がサイクル演算子 'while'に渡される前に、これらの変数の値はそれぞれ1000.0と0.0000000001に等しくなります。 したがって、サイクル演算子への最初の呼び出しで条件は真です。 つまり、条件がテストされた後、コントロールはサイクル演算子本体の最初の演算子に渡されます。
この例では、次の演算子が使用されます。
1 |
<span class="notranslate"> <span class="hl-identifier">私は</span> <span class="hl-code">+ +;</span></span> <span class="notranslate"> <span class="hl-comment">//カウンター</span></span> |
次の3行では、次のシーケンス要素の値が計算されます。
1 2 3 |
<span class="notranslate"> <span class="hl-identifier">A</span> <span class="hl-code">=</span> <span class="hl-identifier">B</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//次の値</span></span> <span class="notranslate"> <span class="hl-identifier">B</span> <span class="hl-code">=</span> <span class="hl-identifier">C</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//</span> <span class="hl-comment">次の値</span></span> <span class="notranslate"> <span class="hl-identifier">C</span> <span class="hl-code">=</span> <span class="hl-identifier">A</span> <span class="hl-code">+</span> <span class="hl-identifier">B</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//</span> <span class="hl-comment">次の値</span></span> |
変数が次の(最も近い)より大きい要素の値を取ることは容易に分かります。 サイクル演算子を実行する前に、A、B、Cの値はそれぞれ1.0,1.0、2.0になりました。 最初の反復では、これらの変数はそれぞれ1.0,2.0および3.0の値をとります。
反復はいくつかの計算の繰り返し実行です。 サイクル演算子本体を構成するプログラム行が実行されていることに注意するために使用されます。
次の行では、シーケンスの後続の(C / B)および前の(B / A)要素に基づいて得られたフィボナッチ数の差を計算します。
1 |
<span class="notranslate"> <span class="hl-identifier">デルタ</span> <span class="hl-code">=</span> <span class="hl-predfunc">MathAbs</span> <span class="hl-brackets">(</span> <span class="hl-identifier">C</span> <span class="hl-code">/</span> <span class="hl-identifier">B</span> <span class="hl-code">-</span> <span class="hl-identifier">B</span> <span class="hl-code">/</span> <span class="hl-identifier">A</span> <span class="hl-brackets">)</span> <span class="hl-code">。</span></span> <span class="notranslate"> <span class="hl-comment">//係数の差を検索する</span></span> |
この演算子では、式の絶対値を計算する標準関数MathAbs()を使用します。 前述のように、フィボナッチ係数は、シーケンス要素の値の増加に伴い、(標準と比較して)より大きい値と小さい値を順番に使用します。 これは、隣接する係数の差が負の値になり、正の値になる理由です。 同時に、この偏差の値そのもの、つまりその絶対値には本当に関心があります。 したがって、フィボナッチ数の現在の値がどの方向にずれていても、式MathAbs(C / B-B / A)の値と変数Deltaの値は常に正です。
この演算子は、サイクル本体を構成する演算子のリストの最後です。 これは、次の行の中かっこの存在によって確認されます。 サイクル本体の最後の演算子が実行された後、その条件をテストするために、制御がサイクル演算子ヘッダーに渡されます。 これは、サイクル演算子の本質を決定する重要なポイントです。 サイクル演算子の条件が真または偽であるため、制御は次の反復またはサイクル演算子の外側に渡されます。
最初の反復では、変数Deltaの値は変数Dで定義された値よりも大きいことがわかります。これは、条件(Delta> D)が真であることを意味します。したがって、制御はサイクル本体に渡されます次の反復を実行します。 計算に含まれるすべての変数には新しい値が使用されます。つまり、サイクルボディの最後に達すると、制御がヘッダーに再び渡され、条件が真であるかどうかがテストされます。
このプロセスは、サイクル演算子の条件が偽になるまで続行されます。 変数Deltaの値がDの値以下になるとすぐに、条件(Delta> D)は真ではありません。 これは、コントロールがサイクル演算子の外を通り、次の行に渡されることを意味します。
1 |
<span class="notranslate"> <span class="hl-predfunc">警告</span> <span class="hl-brackets">(</span> <span class="hl-quotes">"</span> <span class="hl-string">C =</span> <span class="hl-quotes">"</span> <span class="hl-code">、</span> <span class="hl-identifier">C</span> <span class="hl-code">、</span> <span class="hl-quotes">"</span> <span class="hl-string">フィボナッチ数=</span> <span class="hl-quotes">"</span> <span class="hl-code">、</span> <span class="hl-identifier">C</span> <span class="hl-code">/</span> <span class="hl-identifier">B</span> <span class="hl-code">、</span> <span class="hl-quotes">"</span> <span class="hl-string">i =</span> <span class="hl-quotes">"</span> <span class="hl-code">、</span> <span class="hl-identifier">i</span> <span class="hl-brackets">)</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//画面に表示する</span></span> |
その結果、次のメッセージを含むAlert()オペレータウィンドウが画面に表示されます。
С= 317811フィボナッチ数= 1.618 i = 25 |
これは、25回目の反復で検索精度に達し、処理されたフィボナッチ配列要素の最大値が317811に等しいことを意味します。フィボナッチ係数は、予想どおり1.618です。 このメッセージは、問題の解決方法です。
ここで注意すべき点は、MQL4では実数が15桁の精度で計算されることです。 同時にフィボナッチ係数は3桁の精度で表示されます。 これは、関数Alert()が数字の最後にゼロを表示せずに、有効数字4桁までの数字を表示するという事実によって決まります。 あらかじめ定義された精度でフィボナッチ数を表示したい場合は、たとえば次のようにコードを変更する必要があります。
1 |
<span class="notranslate"> <span class="hl-predfunc">警告</span> <span class="hl-brackets">(</span> <span class="hl-quotes">"</span> <span class="hl-string">C =</span> <span class="hl-quotes">"</span> <span class="hl-code">、</span> <span class="hl-identifier">C</span> <span class="hl-code">、</span> <span class="hl-quotes">"</span> <span class="hl-string">フィボナッチ数=</span> <span class="hl-quotes">"</span> <span class="hl-code">、</span> <span class="hl-identifier">C</span> <span class="hl-code">/</span> <span class="hl-identifier">B</span> <span class="hl-code">*</span> <span class="hl-number">10000000</span> <span class="hl-code">、</span> <span class="hl-quotes">"</span> <span class="hl-string">i =</span> <span class="hl-quotes">"</span> <span class="hl-code">、</span> <span class="hl-identifier">i</span> <span class="hl-brackets">)</span> <span class="hl-code">;</span></span> <span class="notranslate"> <span class="hl-comment">//メッセージ</span></span> |
以下に特に注意する必要があります。
サイクル演算子のヘッダーで指定された条件が常に真のままである可能性があります。 この結果、ループが発生します。 |
ループは、 サイクル本体を構成する演算子の連続した繰り返し実行です。 間違ったアルゴリズムを実現した結果、重大な状況になります。
ループが起こると、プログラムはサイクル本体を構成するオペレータのブロックを無限に実行します。 以下は、ループされたサイクル演算子 'while'の簡単な例です:
1 2 3 |
<span class="notranslate"> int i = 1;</span> <span class="notranslate"> //正式なパラメータ(カウンタ)</span> <span class="notranslate"> while(i> 0)//サイクル演算子ヘッダー</span> <span class="notranslate">私は+ +;</span> <span class="notranslate"> // iの値のインクリメント</span> |
上記の例では、変数iの値は繰り返しごとに累積(インクリメント)されます。 その結果、条件が偽になることはありません。 サイクル本体で何も計算されなければ、同様の状況が発生します。 たとえば、以下のコードでは:
1 2 3 |
<span class="notranslate"> int i = 1;</span> <span class="notranslate"> //正式なパラメータ(カウンタ)</span> <span class="notranslate"> while(i> 0)//サイクル演算子ヘッダー</span> <span class="notranslate">アラート( "i ="、i);</span> <span class="notranslate"> //画面に表示する</span> |
サイクル内の変数iの値は変化しません。 次のメッセージが各繰り返しで画面に表示されます。
i = 1 |
このプロセスは無限に繰り返されます。 ループしたコードの罠に陥ったら、コントロールはもうそれを離れることはできません。 この状況は、エキスパートアドバイザーとスクリプトの取引において特に危険です。 このような場合、環境変数は通常更新されません。これは、特殊関数が操作を完了しないのに対し、トレーダーは既存のループを認識しない可能性があるからです。 その結果、実行プログラム内の制御は、受注の開始または終了の決定が行われた対応するプログラム行に渡すことができません。
プログラマは、制御されていないループが可能になるような状態を防ぐ必要があります。 このような状況をプログラムのコンパイルや実行時にプログラムで発見する手助けとなるテクニックはありません。 このようなアルゴリズム上のエラーを検出する唯一の方法は、コード(論理的な推論と常識)を詳しく調べることです。