MQL4、MQL5に関する初心者からの質問、アルゴリズムやコードに関するヘルプ、ディスカッションなど。 - ページ 808

 
Kos Mos:

だから、自分が何に失敗しているのかを探そうとしている。誰もタダで教えてくれそうもないことは理解している--資本主義のせいだ)。私はそれに反対するものは何もありません。ただ、なぜ買い方向のすべてのローソク足でトレードが始まるのかを理解する必要があります。

私はあなたに答えていたのではありません。

スキーを動かしたいなら、少なくとも信号を受信したときに重要な変数の値をプリントして、それがどうなるかをログで確認する必要があるのです。

 

for(int i=0;i<ArrayRange(arr2,0);i++) というループがありますが、このArrayRange(arr2,0)の計算が何回行われているのか知りたいです。一回で機械が値を覚えているのか、ループ実行時に毎回、ArrayRange(arr2,0)関数から 値が返されているのか?例

第1オプション

i=0,i<(戻り値)でインクリメント、その後

i<(再度戻り値)の場合、インクリメント、その後

i<(再び値を返す)の場合、このようにインクリメントします。

2ndバリアント。

あるいは、この計算から一度ArrayRange(arr2,0)で値を返し、5を返させ、機械がこの5を記憶して次の結果を得ます。

i=0,i<(戻り値)i<5,インクリメント,その後

i<5,インクリメント,その後

i<5, increment - こんな感じでしょうか?

なぜかというと、最初の変形によってすべてが起こるのであれば、ループの前にこの値を取り出して変数に格納しておけば、プログラムがループパスのたびに ArrayRange(arr2,0) 関数を計算することがなくなるので、理にかなっているのです。

 
Seric29:

for(int i=0;i<ArrayRange(arr2,0);i++) というループがありますが、このArrayRange(arr2,0)の計算が何回行われているのか知りたいのですが、一度で機械が値を覚えているのか、ループ実行中に毎回ArrayRange(arr2,0)の関数から 値を返しているのか、どちらなのでしょう?例

第1オプション

i=0,i<(戻り値)でインクリメント、その後

i<(再度戻り値)の場合、インクリメント、その後

i<(再び値を返す)の場合、このようにインクリメントします。

2ndバリアント。

あるいは、この計算から一度ArrayRange(arr2,0)で値を返し、5を返させ、機械がこの5を記憶して次のような結果が得られます。

i=0,i<(戻り値)i<5,インクリメント,その後

i<5,インクリメント,その後

i<5, increment - こんな感じでしょうか?

なぜかというと、もしすべてが最初のバリアントで起こるなら、ループの前にまずこの値を取り出して変数に格納することは意味があり、ループの各通過でプログラムが関数 ArrayRange(arr2,0) を作らないようにするためです。

一般的な場合 - 1の場合

PS/ 2番目は、ループの中にArrayResizeがなければ、ArrayRange:=constと理解できる「最適化」コンパイラにのみ可能です。

PPS/ ArrayRange()の例は正確ではありません。なぜなら、おそらく直接関数を呼び出すことはなく、コンパイラは配列について何でも知っているので、iと内部配列変数を比較することに還元しなければならないだけだからです。

 
Maxim Kuznetsov:

一般的な場合 - 第 1 バリアント。

PS/ 2番目は、ループ内にArrayResizeがない場合、ArrayRange:=constと理解できる「最適化」コンパイラにのみ可能です; mqlコンパイラがすでにそこまでコードを深く掘り下げているかどうかは分かりませんが、「ネイティブ」関数では理論的に可能です。

PPS/ArrayRange()の例は正確ではありません。なぜなら、おそらく直接関数を呼び出すことはなく、コンパイラは配列についてすべて知っているので、iと内部配列変数の比較に還元しなければならないからです。

5+5*5 式を例にとると

第1バリアント

i=0,i<(5+5*5)でインクリメント、次に

i<(5+5*5)ならインクリメント

i<(5+5*5), このようにインクリメントする。

2ndバリアント。

とか、この場合、5+5*5の1回返しで、30を返させて、この30区を機械が記憶しているので、次のような結果になる。

i=0,i<(戻り値) i<30, 増分, 次(30をどこかに保存していなかったので、エンジンは自動的に30を記憶している)

i<30でインクリメント、その後

i<30、インクリメント、こんな感じでしょうか?

1stバリエーションになるんですね?5+5*5 はループの各反復で評価される式である。この式をループの前に計算して30を変数に格納し、ループの中で代入すれば、プログラムが自動的にこの30を計算してメモリに格納しない限り、この方が使い勝手がよいでしょう。


関数呼び出しがない場合、コンパイラは i<5 という真偽値をチェックできないので、おそらく最初のオプションがうまくいくでしょう。

 

ループや関数の中で、関数(ArrayRange)の結果を変更することができる。
そして、定数式(5+5*5)は常に同じになる。

したがって、関数はパスごとに計算されることになります。
そして、その定数値はコンパイル時にコンパイラによってコードに代入される。

 
Taras Slobodyanik:

ループや関数の中で、関数(ArrayRange)の結果を変更することができる。
そして、定数式(5+5*5)は常に同じになる。

したがって、関数はパスごとに計算されることになります。
そして、その定数値はコンパイル時にコンパイラによってコードに代入される。

5+5*5 は式でもあり、各パスで計算する必要があります。関数に関しては、同じ結果を返すことが期待されます。

int k=5+5*5;//k=30

for(int i=0;i<k;i++){}

ここで、kは常に30または

int k=ArrayRange(arr2,0)//k=5

for(int i=0;i<k;i++){}

ここで、kは常に5である。

 
Seric29:

5+5*5 は式でもあり、すべてのパスで計算されるはずです。関数については同じ結果を返すはずですが、ポイントは、ループのすべてのパスでコンパイラが関数と式 5+5*5 の両方をカウントすることです。つまり、最初の選択肢になります。ループのすべてのパスで計算されているので、ループ前にこの値をカウントして変数に保存して、ループのすべてのパスで計算しないように同じ固定値として変数を使用すると理にかなっている、それは結局できます。

int k=5+5*5;//k=30

for(int i=0;i<k;i++){}

ここで、kは常に30または

int k=ArrayRange(arr2,0)//k=5

for(int i=0;i<k;i++){}

ここで、kは常に5に等しい。

ループを展開するだけで、余分な変数を作らないようにすることができます。

 
Seric29:

5+5*5 は式でもあり、各パスで計算する必要があります。関数については同じ結果を返すことになっていますが、サイクルの各パスでコンパイラが関数と式 5+5*5 の両方をカウントすることについて話しています。そこで、最初のオプションがあります。つまり、サイクルの各パスで計算されるので、サイクル前にこの値をカウントして変数に格納し、同じ静的値として変数を使用すればサイクルの各パスでの計算がない、結局はモ

コンパイラは常に一度だけ、つまりテキストをコードにコンパイルする瞬間に動作します。
(私の記憶では、MT4もすでにコードに直接コンパイルしています)

5+5*5 - これは定数を使った式で、再計算の必要がありません。したがって、コンパイル時に一度だけ計算され、コードには30という数字が含まれます。

5+5*5+i は変数を含む式で、これは各パスで 30+i としてコード内で計算されます。

ArrayRange 関数は値を返しますが、コンパイラはこの値が何であるかを知らないので、コード内の関数呼び出しを代入し、各パス(コード内)で関数は
 
Taras Slobodyanik:

コンパイラは常に一度だけ、つまりテキストをコードにコンパイルする瞬間に動作します。
(私の記憶では、MT4はすでにコードに直接コンパイルしています)

5+5*5 は定数を含む式で、再計算の必要はありません。したがって、これはコンパイル時に一度だけ計算され、コードでは 30 となります。

5+5*5+i は変数を含む式で、各パスで 30+i としてコード内で計算されます。

ArrayRange 関数は値を返しますが、コンパイラはこの値が何であるかを知らないので、コード内の関数呼び出しを代入し、各パス(コード内)で関数は

なるほど。ありがとうございます。もちろん、深刻な問題ではありませんが、微妙なところがあります。

 
Artyom Trishkin:

ループを展開するだけで、余分な変数を作らずに済みます。

私の場合、2つの数式があります。 1番目-ArrayRange(arr2,0) 2番目5+5*5 私の目標は、コンパイラがより少ない負荷で動作 するような条件を作ることです。

for(int i=0;i<ArrayRange(arr2,0);i++) この場合、比較値は各パスで返さ れます。

int k=ArrayRange(arr2,0)//k=5 for(int i=0;i<k;i++){} この場合、比較値は4回ではなく1回返されますが、変数が作成され、それでも特に数千や数百万について話すときは負荷が低くなります。

変数を作らなくてもいいように、ループを展開する方法を教えてください。