mql5语言的特点、微妙之处以及技巧 - 页 116

 
Ilya Malev:

(累)如果是这个问题,就会弹出"'k'--重新定义;不同的类型修改器 "的错误,但在截图上没有。所以编译器并不关心,这不是问题所在。

嗯,嗯...

 
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)]);
};

两个函数都给出了正确的相同答案,我没有发现错误。

比较操作的速度是很有趣的。我的版本的移位和加法运算略少,但最后有乘法运算。 Alexey的版本的移位和加法运算略多,但没有乘法运算。怎么会更快?

 
 
 
Georgiy Merts:

我的版本中移位和加法运算略少,但没有乘法运算。 Alexey的版本中移位和加法运算略多,但没有乘法运算。怎么会更快呢?

最多 有6次移位和加法操作(二进制搜索)。移位(ulong)1<<k不算,因为它是一个常数。唯一的问题是,我们也要检查病情。但总是 有6个操作,加上乘法,再加上一个移位和对管理数组的访问(即索引检查)。所以你的版本显然在速度上会慢一些:)。

而你的版本当然看起来很神秘)。

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选项更快。


明白了。

取代我的功能。