Особенности языка mql5, тонкости и приёмы работы - страница 116

 
Ilya Malev:

(устало) если бы в этом была проблема, то вылезла бы ошибка "'k' - redefinition; different type modifiers", но на скрине её нет. Значит компилятору все равно и дело не в этом.

Ну-ну...

 
Alexey Navoykov:

Ну-ну...

Ну попробуйте сами откомпилировать. Если не лень посты писать на эту тему на форуме, должно быть не лень и загнать в редактор и нажать F7. Это гораздо быстрее.

 

Быстрый способ вычисления двоичного логарифма целого числа.  Работает в 3-5 раз быстрее, чем расчёт через MathLog.

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 будет работать на терминале MT4 ? Где то что то читал, что будет работать.
 
Alexey Navoykov:

Быстрый способ вычисления двоичного логарифма целого числа.  Работает в 3-5 раз быстрее, чем расчёт через MathLog.

Я использую такую функцию (чистое шаманство, но работает):

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:

В моем варианте - чуть меньше операций сдвига и сложения, но в конце есть умножение. В варианте Алексея - операций сдвига и сложения чуть больше, но умножения нет. Как быстрее ?

У меня операций сдвига и сложения - не более 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 быстрее.


Понял.

Заменяю свою функцию.

Причина обращения: