mql5言語の特徴、微妙なニュアンスとテクニック - ページ 116

 
Ilya Malev:

(疲れ) もしそれが問題なら、「'k' - redefinition; different type modifiers」というエラーが出るはずですが、スクリーンショットには出てきませんね。だから、コンパイラは気に しないし、問題にもならない。

さて、さて...

 
Alexey Navoykov:

さて、さて...

まあ、自分でコンパイルしてみてください。この話題で掲示板に書き込みをするのが億劫なら、エディターに入れてF7を押すのも億劫になるはずです。より高速になりました。

 

整数の両対数を高速に計算する。MathLogの 3-5倍高速に動作する。

int log2(ulong n)
{
  if (n==0) return -1;
  
  #define  S(k) if (n >= (ulong(1)<<k)) { i += k;  n >>= k; }
  
  int i=0;  S(32);  S(16);  S(8);  S(4);  S(2);  S(1);  return i;
  
  #undef  S
}
 
MQL5で書かれたEAは、MT4ターミナルで動作しますか?どこかで読んだのですが、効果があるのでしょうか?
 
Alexey Navoykov:

整数の両対数を高速に計算する。 MathLogの3-5倍高速に動作する。

私はこのような機能を使っています(純粋なシャーマニズムですが、うまくいきます)。

static const uint ulLogTable[64] = 
{
0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63 
};


uint _FastLog2(ulong ulInput)
{
   ulInput |= ulInput >> 1;
   ulInput |= ulInput >> 2;
   ulInput |= ulInput >> 4;
   ulInput |= ulInput >> 8;
   ulInput |= ulInput >> 16;
   ulInput |= ulInput >> 32;
  
   return(ulLogTable[(uint)((ulInput * 0x03f6eaf2cd271461) >> 58)]);
};

どちらの関数も正しい同じ答えを出し、エラーは見つかりませんでした。

動作速度の比較は面白いですね。私のバージョンは、シフトと足し算の演算が少し少ないですが、最後に掛け算があります。 アレクセイのバージョンは、シフトと足し算の演算が少し多いですが、掛け算がありません。どのように速くなったのですか?

 
このトピックに関係のないコメントは、「MQL4に関する初心者の質問、アルゴリズムやコードに関するヘルプや議論」に移動しました。
 
このトピックに関係のないコメントは、「MQL4に関する初心者の質問、アルゴリズムやコードに関するヘルプや議論」に移動しました。
 
Georgiy Merts:

私のバージョンは、シフトと足し算の演算が少し少なく、掛け算はありません。 Alexeyのバージョンは、シフトと足し算の演算が少し多く、掛け算はありません。どのように速くなったのですか?

シフトと加算の演算(バイナリサーチ)は最大 6回です。シフト(ulong)1<<kは定数なのでカウント されません。ただ、状態も確認します。しかし、常に 6回の演算があり、さらに乗算、さらに1回のシフトと管理対象配列へのアクセス(つまりインデックスチェック)があります。ですから、あなたのバージョンは明らかに速度が遅くなります :) 。

そして、あなたのバージョンはもちろん神秘的に見えます(笑)。

p.s. 私の推測では、もし私のコードがif-elseによる比較の連鎖にラップされず、すべての算術演算を 取り除くことができれば、ものすごく速くなる。 しかし、それはコードの大きな混乱になる。 マクロで再帰が使えればいいのだが........。

 
Georgiy Merts:

速度を比較するのも面白いですね。

log2 バリアントはより高速です。

#property strict
#define    test(M,S,EX)        {uint mss=GetTickCount();uint nn=(uint)pow(10,M);for(uint t12=0;t12<nn;t12++){EX;} \
                                printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}

int log2(ulong n){
  if (n==0) return -1;
  #define  S(k) if (n >= (ulong(1)<<k)) { i += k;  n >>= k; }
  int i=0;  S(32);  S(16);  S(8);  S(4);  S(2);  S(1);  return i;
  #undef  S}


static const uint ulLogTable[64] = {
0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61,
51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56,
45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63 };

uint _FastLog2(ulong ulInput){
   ulInput |= ulInput >> 1;
   ulInput |= ulInput >> 2;
   ulInput |= ulInput >> 4;
   ulInput |= ulInput >> 8;
   ulInput |= ulInput >> 16;
   ulInput |= ulInput >> 32;  
   return(ulLogTable[(uint)((ulInput * 0x03f6eaf2cd271461) >> 58)]);};

void OnStart(){
  srand(GetTickCount());
  ulong n,n1;
  test(8,"MathLog",n=rand()*rand();n1=ulong(MathLog(n)/MathLog(2)))
  test(8,"log2",n=rand()*rand();n1=log2(n);)
  test(8,"_FastLog2",n=rand()*rand();n1=_FastLog2(n))}


 
Ilya Malev:

つまり、log2オプションの方が高速なのです。


了解です。

自分の機能を置き換える。

理由: