Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 116

 
Ilya Malev:

(stanco) se questo fosse il problema, l'errore "'k' - redefinition; different type modifiers" apparirebbe, ma non è nello screenshot. Quindi al compilatore non interessa e non è questo il problema.

Bene, bene...

 
Alexey Navoykov:

Bene, bene...

Beh, provate a compilarlo voi stessi. Se non sei troppo pigro per scrivere post su questo argomento sul forum, dovresti essere troppo pigro per metterlo in un editor e premere F7. È molto più veloce.

 

Modo veloce per calcolare il logaritmo binario di un intero. Funziona 3-5 volte più veloce di 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
}
 
Un EA scritto in MQL5 funzionerà su un terminale MT4? Ho letto da qualche parte che funzionerà.
 
Alexey Navoykov:

Modo veloce per calcolare il logaritmo binario di un intero. Funziona 3-5 volte più veloce di MathLog.

Io uso una funzione come questa (puro sciamanesimo, ma funziona):

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

Entrambe le funzioni danno la stessa risposta corretta, non ho trovato errori.

È interessante confrontare la velocità di funzionamento. La mia versione ha un po' meno operazioni di spostamento e di addizione, ma c'è la moltiplicazione alla fine. La versione di Alexey ha un po' più operazioni di spostamento e di addizione, ma nessuna moltiplicazione. In che modo è più veloce?

 
I commenti non relativi a questo argomento sono stati spostati in "Tutte le domande dei neofiti su MQL4, aiuto e discussione su algoritmi e codici".
 
I commenti non relativi a questo argomento sono stati spostati in "Tutte le domande dei neofiti su MQL4, aiuto e discussione su algoritmi e codici".
 
Georgiy Merts:

La mia versione ha un po' meno operazioni di spostamento e di addizione, ma non di moltiplicazione; quella di Alexey ha un po' più operazioni di spostamento e di addizione, ma non di moltiplicazione. In che modo è più veloce?

Ho un massimo di 6 operazioni di shift e di addizione (ricerca binaria).Shift (ulong)1<<k non conta, perché è una costante. L'unica cosa è che controlliamo anche le condizioni. Ma ci sono sempre 6 operazioni, più la moltiplicazione, più un ulteriore spostamento e l'accesso all'array gestito (cioè il controllo dell'indice). Quindi la tua versione sarà ovviamente più lenta per velocità :).

E la tua versione, naturalmente, sembra misteriosa).

p.s. Ho un'ipotesi, che se il mio codice potesse essere srotolato in una catena di confronti via if-else, liberandosi di tutte le operazioni aritmetiche, velocizzerebbe enormemente le cose. Ma sarebbe un gran casino di codice. Se solo si potesse usare la ricorsione nelle macro...

 
Georgiy Merts:

È interessante confrontare la velocità.

La variante log2 è più veloce.

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

Quindi l'opzione log2 è più veloce.


Capito.

Sostituzione della mia funzione.

Motivazione: