Características da linguagem mql5, subtilezas e técnicas - página 116

 
Ilya Malev:

(cansado) se esse fosse o problema, o erro "'k' - redefinição; modificadores de tipo diferente" apareceria, mas não está na imagem do ecrã. Portanto, o compilador não se importa e não é esse o problema.

Ora bem, ora bem...

 
Alexey Navoykov:

Ora bem, ora bem...

Bem, tente compilá-lo você mesmo. Se não for demasiado preguiçoso para escrever mensagens sobre este tópico no fórum, deve ser demasiado preguiçoso para o colocar num editor e carregar em F7. É muito mais rápido.

 

Forma rápida de calcular o logaritmo binário de um número inteiro. Funciona 3-5 vezes mais rápido do que o 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
}
 
Um EA escrito em MQL5 irá funcionar num terminal MT4? Li algures que vai funcionar.
 
Alexey Navoykov:

Forma rápida de calcular o logaritmo binário de um número inteiro. Funciona 3-5 vezes mais rápido do que o MathLog.

Eu uso uma função como esta (puro xamanismo, mas funciona):

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

Ambas as funções dão a mesma resposta correcta, não encontrei erros.

É interessante comparar a velocidade de operação. A minha versão tem um pouco menos de operações de mudança e adição, mas há multiplicação no final. A versão de Alexey tem um pouco mais de operações de mudança e adição, mas não há multiplicação. Como é mais rápido?

 
Comentários não relacionados com este tópico foram movidos para"Quaisquer perguntas de novatos sobre MQL4, ajuda e discussão sobre algoritmos e códigos".
 
Comentários não relacionados com este tópico foram movidos para"Quaisquer perguntas de novatos sobre MQL4, ajuda e discussão sobre algoritmos e códigos".
 
Georgiy Merts:

A minha versão tem um pouco menos de operações de turno e de adição, mas não de multiplicação. A versão de Alexey tem um pouco mais de operações de turno e de adição, mas não de multiplicação. Como é mais rápido?

Tenho um máximo de 6 operações de turno e adição (pesquisa binária). Oturno (ulong)1<<k não conta, porque é uma constante. A única coisa é que também verificamos a condição. Mas há sempre 6 operações, mais a multiplicação, mais um turno e acesso à matriz gerida (isto é, verificação do índice). Assim, a sua versão será obviamente mais lenta por velocidade :).

E a sua versão, claro, parece misteriosa).

p.s. Tenho uma suposição, que se o meu código pudesse ser desembrulhado numa cadeia de comparações via if-else, livrando-se de todas as operações aritméticas, aceleraria tremendamente as coisas. Mas seria uma grande confusão de código. Se ao menos se pudesse usar a recorrência em macros...

 
Georgiy Merts:

É interessante comparar a velocidade.

A variante log2 é mais rápida.

#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:

Assim, a opção log2 é mais rápida.


Já está.

Substituição da minha função.

Razão: