Mql5 dilinin özellikleri, incelikleri ve çalışma yöntemleri - sayfa 122

 
Anahtarın hızlandırılabileceği bir durumla karşılaştım
 #define MACROS2 \
  MACROS( 0 )     \
  MACROS( 1 )     \
  MACROS( 2 )     \
  MACROS( 3 )     \
  MACROS( 4 )     \
  MACROS( 5 )     \
  MACROS( 6 )     \
  MACROS( 7 )     \
  MACROS( 8 )     \
  MACROS( 9 )

double Math( const double Value ) { return ( MathSqrt (Value)); }

typedef double (*SUMFUNC)( void );

#define MACROS(A) double SumFunc ##A() { return (Math(A + 1 )); }
  MACROS2
#undef MACROS

SUMFUNC SumFunc[ 10 ];

bool Init()
{
#define MACROS(A) SumFunc[A] = SumFunc ##A;
   MACROS2
#undef MACROS
  
   return ( true );
}

const bool Init = Init();

// Через switch
void SwitchFunc1( const int Value, double &Sum )
{    
   switch (Value)
  {
   #define MACROS(A) case A: Sum += Math(A + 1 ); break ;
    MACROS2
   #undef MACROS    
  }
}

// Через массив указателей на функции
void SwitchFunc2( const int Value, double &Sum )
{
  Sum += SumFunc[Value]();
}

// Через switch2
void SwitchFunc3( const int Value, double &Sum )
{    
   switch (Value)
  {
   #define MACROS(A) case A: Sum += SumFunc ##A(); break ;
    MACROS2
   #undef MACROS    
  }
}

typedef void (*SWITCHFUNC)( const int , double & );

void Bench( SWITCHFUNC SwitchFunc )
{
   double Sum = 0 ;
  
   MathSrand ( 0 );
  
   for ( int i = 0 ; i < 1 e8; i++)
    SwitchFunc( MathRand () % 10 , Sum);
    
   Print (Sum);
}

#define BENCH(A)                                                              \
{                                                                             \
   const ulong StartTime = GetMicrosecondCount ();                              \
  A;                                                                          \
   Print ( "Time[" + #A + "] = " + ( string )( GetMicrosecondCount () - StartTime)); \
}  

void OnStart ()
{
  BENCH(Bench(SwitchFunc1))
  BENCH(Bench(SwitchFunc2))  
  BENCH(Bench(SwitchFunc3))  
}


Sonuç

 224677638.4805779
Time [Bench(SwitchFunc1)] = 635995
224677638.4805779
Time [Bench(SwitchFunc2)] = 1646031
224677638.4805779
Time [Bench(SwitchFunc3)] = 1593283


Üçüncü seçenek (anahtar), ikincisinden (işlev işaretçileri) sürekli olarak daha yavaştır. Bu hangi nedenle oluyor?


ZY fren yapıyorum. Üçüncüsü ikincisinden daha hızlıdır. Pekala.


ZYY İşlevler için değişmez bir işaretçi dizisi varsa, bunun yerine anahtarla değiştirilirse daha hızlı olacağı ortaya çıktı.

Почему Switch/Case, а не If/Else If?
  • 2009.06.22
  • OB OB
  • qaru.site
Этот вопрос в основном указывается на C/С++, но я думаю, что другие языки также актуальны. Я не могу понять, почему используется параметр switch/case вместо if/else if. Мне очень нравится использование goto's и приводит к тому же виду беспорядочного кода, в то время как те же результаты могут быть достигнуты с if/else, если более организованным...
 
fxsaber :


ZYY İşlevler için değişmez bir işaretçi dizisi varsa, bunun yerine anahtarla değiştirilirse daha hızlı olacağı ortaya çıktı.

Eh, bu durumda, mantıklı çünkü. dizi dinamik olarak doldurulmuştur, bu da işaretçilerin geçerliliği için sürekli kontroller olduğu anlamına gelir. Kesinlikle optimize edilebilir olsa da ...

Şimdi, eğer MQL sabit işaretçilerle dizi başlatmayı destekliyorsa, o zaman belki de aynı olurdu.

not; Kodunuz tamamen okunamıyor. Tabii ki, makrolarla ilgili bu çan ve ıslıklarla rahat olduğunuzu anlıyorum, çünkü bunları kendiniz yazdınız, böylece ne yaptıklarını bilirsiniz. Ama dışarıdan okuyucu için bu sadece bir bilmece. Bunu neden yayınlasın? Sanırım altı ay içinde burada ne yaptığınızı anlamanız pek mümkün değil) Keşke yorumlar chtol yapsaydı ...

 
Alexey Navoykov :

not; Kodunuz tamamen okunamıyor. Tabii ki, makrolarla ilgili bu çan ve ıslıklarla rahat olduğunuzu anlıyorum, çünkü bunları kendiniz yazdınız, böylece ne yaptıklarını bilirsiniz. Ama dışarıdan okuyucu için bu sadece bir bilmece. Bunu neden yayınlasın? Sanırım altı ay içinde burada ne yaptığınızı anlamanız pek mümkün değil) Keşke yorumlar chtol yapsaydı ...

Aksi takdirde bir ayak bezi olurdu. Ayrıca, geçiş sayısı ile denendi. Makrolar olmadan bunu yapmak zor olurdu. Ekleme ile ilgili. yorumlar - Gelecekte dikkate alacağım.

 
fxsaber :

Aksi takdirde bir ayak bezi olurdu. Ayrıca, geçiş sayısı ile denendi. Makrolar olmadan bunu yapmak zor olurdu. Ekleme ile ilgili. yorumlar - Gelecekte dikkate alacağım.

Bazen anlaşılır bir ayak örtüsünü sökmek, kompakt bir bilmeceyi sökmeye başlamaktan ve bu işe yaramaz alıştırmayı hemen terk etmekten çok daha kolaydır.

 
Artyom Trishkin :

Bazen anlaşılır bir ayak örtüsünü sökmek, kompakt bir bilmeceyi sökmeye başlamaktan ve bu işe yaramaz alıştırmayı hemen terk etmekten çok daha kolaydır.

 double Math( const double Value ) { return ( MathSqrt (Value)); }

typedef double (*SUMFUNC)( void );

double SumFunc0() { return (Math( 0 + 1 )); }
double SumFunc1() { return (Math( 1 + 1 )); }
double SumFunc2() { return (Math( 2 + 1 )); }
double SumFunc3() { return (Math( 3 + 1 )); }
double SumFunc4() { return (Math( 4 + 1 )); }
double SumFunc5() { return (Math( 5 + 1 )); }
double SumFunc6() { return (Math( 6 + 1 )); }
double SumFunc7() { return (Math( 7 + 1 )); }
double SumFunc8() { return (Math( 8 + 1 )); }
double SumFunc9() { return (Math( 9 + 1 )); }

SUMFUNC SumFunc[ 10 ];

bool Init()
{
  SumFunc[ 0 ] = SumFunc0;
  SumFunc[ 1 ] = SumFunc1;
  SumFunc[ 2 ] = SumFunc2;
  SumFunc[ 3 ] = SumFunc3;
  SumFunc[ 4 ] = SumFunc4;
  SumFunc[ 5 ] = SumFunc5;
  SumFunc[ 6 ] = SumFunc6;
  SumFunc[ 7 ] = SumFunc7;
  SumFunc[ 8 ] = SumFunc8;
  SumFunc[ 9 ] = SumFunc9;
  
   return ( true );
}

const bool Init = Init();

// Через switch
void SwitchFunc1( const int Value, double &Sum )
{    
   switch (Value)
  {
   case 0 : Sum += Math( 0 + 1 ); break ;
   case 1 : Sum += Math( 1 + 1 ); break ;
   case 2 : Sum += Math( 2 + 1 ); break ;
   case 3 : Sum += Math( 3 + 1 ); break ;
   case 4 : Sum += Math( 4 + 1 ); break ;
   case 5 : Sum += Math( 5 + 1 ); break ;
   case 6 : Sum += Math( 6 + 1 ); break ;
   case 7 : Sum += Math( 7 + 1 ); break ;
   case 8 : Sum += Math( 8 + 1 ); break ;
   case 9 : Sum += Math( 9 + 1 ); break ;
  }
}

// Через массив указателей на функции
void SwitchFunc2( const int Value, double &Sum )
{
  Sum += SumFunc[Value]();
}

// Через switch2
void SwitchFunc3( const int Value, double &Sum )
{    
   switch (Value)
  {
   case 0 : Sum += SumFunc0(); break ;
   case 1 : Sum += SumFunc1(); break ;
   case 2 : Sum += SumFunc2(); break ;
   case 3 : Sum += SumFunc3(); break ;
   case 4 : Sum += SumFunc4(); break ;
   case 5 : Sum += SumFunc5(); break ;
   case 6 : Sum += SumFunc6(); break ;
   case 7 : Sum += SumFunc7(); break ;
   case 8 : Sum += SumFunc8(); break ;
   case 9 : Sum += SumFunc9(); break ;
  }
}

typedef void (*SWITCHFUNC)( const int , double & );

void Bench( SWITCHFUNC SwitchFunc )
{
   double Sum = 0 ;
  
   MathSrand ( 0 );
  
   for ( int i = 0 ; i < 1 e8; i++)
    SwitchFunc( MathRand () % 10 , Sum);
    
   Print (Sum);
}

#define BENCH(A)                                                              \
{                                                                             \
   const ulong StartTime = GetMicrosecondCount ();                              \
  A;                                                                          \
   Print ( "Time[" + #A + "] = " + ( string )( GetMicrosecondCount () - StartTime)); \
}  

void OnStart ()
{
  BENCH(Bench(SwitchFunc1))
  BENCH(Bench(SwitchFunc2))  
  BENCH(Bench(SwitchFunc3))  
}
 

Daha önce söylenenlere ek olarak, Test Cihazındaki aynı çalışmaların uyumsuzluğunun en yaygın nedenlerinden biri hatalı başlatma veya yokluğudur.


Değişkenlerin başlatılmasının olmaması basitse, dizilerle biraz daha karmaşıktır. Çoğu zaman, dizi öğelerinin sayısının arttığı durumları bulmak sorunlu bir yeri gösterebilir.


Bu tür olası sorunları yakalamak için danışmanın başına aşağıdaki satırları ekleyebilirsiniz.

 // Помогает найти причину потенциальной ошибочной инициализации
template < typename T>
int ArrayResize2( T &Array[], const int NewSize, const string Str )
{
   const int PrevSize = ArraySize (Array);
   const int Res = ArrayResize (Array, NewSize);
  
   if ((PrevSize < NewSize) || (Res != NewSize))
  {
   #define TOSTRING(A) ", " + #A + " = " + ( string )(A)
     Print (Str + ( string )Res + TOSTRING(PrevSize) + TOSTRING(NewSize));
   #undef TOSTRING     
  
    TesterStop();
  }
  
   return (Res);
}

// Вариант с Reserve != 0 не предусмотрен
#define ArrayResize (A,B) ArrayResize2(A, B, __FUNCSIG__ + ", Line = " + ( string ) __LINE__ + \
                                             ": ArrayResize(" + #A + ", " + #B + ") = " )
 // Помогает найти причину потенциальной ошибочной инициализации
template < typename T1, typename T2>
int ArrayInitialize2( T1 &Array[], const T2 Value, const string Str )
{
   const int Res = ArrayInitialize (Array, Value);
  
   if (! ArraySize (Array) || !Res)
  {
   #define TOSTRING(A) ", " + #A + " = " + ( string )(A)
     Print (Str + ( string )Res + TOSTRING( ArraySize (Array)));
   #undef TOSTRING     
  
    TesterStop();
  }
  
   return (Res);
}

#define ArrayInitialize (A,B) ArrayInitialize2(A, B, __FUNCSIG__ + ", Line = " + ( string ) __LINE__ +  \
                                                     ": ArrayInitialize(" + #A + ", " + #B + ") = " )


Durum yakalanırsa, günlükte ayrıntılı bilgi görüntülenecek ve çalıştırma durdurulacaktır.


ZY Uygulama örneği .

 
Yeniden boyutlandırma ile açık, ben de sık sık benzer bir yöntem kullanıyorum, peki ya başlatma? Nasıl yanılıyor olabilir?
 
Alexey Navoykov :
Yeniden boyutlandırma ile açık, ben de sık sık benzer bir yöntem kullanıyorum, peki ya başlatma? Nasıl yanılıyor olabilir?

Örneğin, ArrayResize ve ArrayInitialize karıştırılmıştır. Veya örneğin gösterge, yanlışlıkla arabelleğin başlatıldığını düşünerek OnInit'te arabelleği ArrayInitialize yapar.

 
fxsaber :

Örneğin, ArrayResize ve ArrayInitialize karıştırılmıştır.

Bu çocukça bir hata. Onu bulmak için çabaya değer mi?

 
Ilya Malev :

Bu çocukça bir hata. Bulmak için çabaya değer mi?

Herhangi bir hatayı bulmak çaba gerektirir. Özellikle kod büyükse ve size ait değilse.