mql5 언어의 특징, 미묘함 및 작업 방법 - 페이지 122

 
전환 속도를 높일 수 있는 상황이 발생했습니다.
 #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))  
}


결과

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


세 번째 옵션(스위치)은 두 번째(함수 포인터)보다 일관되게 느립니다. 어떤 이유로 이런 일이 발생합니까?


ZY I 브레이크. 세 번째는 두 번째보다 빠릅니다. 괜찮은.


ZYY 함수에 대한 포인터의 변경 불가능한 배열이 있는 경우 스위치로 대체하면 더 빠릅니다.

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


ZYY 함수에 대한 포인터의 변경 불가능한 배열이 있는 경우 스위치로 대체하면 더 빠릅니다.

글쎄,이 경우 논리적이기 때문에. 배열이 동적으로 채워졌습니다. 즉, 포인터의 유효성을 지속적으로 확인합니다. 확실히 최적화 될 수 있지만 ...

이제 MQL이 상수 포인터를 사용하여 배열 초기화 를 지원했다면 아마도 같을 것입니다.

p.s. 귀하의 코드는 완전히 읽을 수 없습니다. 물론 매크로가 포함된 이러한 종소리와 휘파람은 사용자가 직접 작성했기 때문에 그들이 하는 일을 알 수 있다는 점을 이해합니다. 그러나 외부 독자에게는 퍼즐일 뿐입니다. 왜 이것을 게시합니까? 6개월 만에 너 자신이 여기에서 한 일을 이해하지 못할 것 같다.) 댓글만 chtol 했다면 ...

 
Alexey Navoykov :

p.s. 귀하의 코드는 완전히 읽을 수 없습니다. 물론, 나는 당신이 매크로를 사용하여 이러한 종소리와 휘파람을 편안하게 이해한다는 것을 이해합니다. 그러나 외부 독자에게는 퍼즐일 뿐입니다. 왜 이것을 게시합니까? 6개월 만에 너 자신이 여기에서 한 일을 이해하지 못할 것 같다.) 댓글만 chtol 했다면 ...

그렇지 않으면 족쇄가 될 것입니다. 또한 전환 횟수를 실험했습니다. 매크로 없이는 이 작업을 수행하기 어렵습니다. 추가에 대해. 의견 - 앞으로 고려하겠습니다.

 
fxsaber :

그렇지 않으면 족쇄가 될 것입니다. 또한 전환 횟수를 실험했습니다. 매크로 없이는 이 작업을 수행하기 어렵습니다. 추가에 대해. 의견 - 앞으로 고려하겠습니다.

때로는 컴팩트 rebus 분해를 시작하고이 쓸모없는 운동을 즉시 포기하는 것보다 이해할 수있는 족보를 분해하는 것이 훨씬 쉽습니다.

 
Artyom Trishkin :

때로는 컴팩트 rebus 분해를 시작하고이 쓸모없는 운동을 즉시 포기하는 것보다 이해할 수있는 족보를 분해하는 것이 훨씬 쉽습니다.

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

이미 말한 것 외에도 테스터에서 동일한 실행이 일치하지 않는 가장 일반적인 이유 중 하나는 잘못된 초기화 또는 부재입니다.


변수 초기화의 부족이 단순하다면 배열의 경우 다소 복잡합니다. 대부분의 경우 배열 요소 의 수가 증가하는 상황을 찾는 것은 문제가 있는 위치를 나타낼 수 있습니다.


이러한 잠재적인 문제를 파악하기 위해 어드바이저의 시작 부분에 다음 줄을 삽입할 수 있습니다.

 // Помогает найти причину потенциальной ошибочной инициализации
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 + ") = " )


상황이 포착되면 자세한 정보가 로그에 표시되고 실행이 중지됩니다.


ZY 적용 .

 
크기 조정은 분명합니다. 저도 비슷한 방법을 자주 사용하지만 초기화는 어떻습니까? 그녀가 어떻게 틀릴 수 있습니까?
 
Alexey Navoykov :
크기 조정은 분명합니다. 저도 비슷한 방법을 자주 사용하지만 초기화는 어떻습니까? 그녀가 어떻게 틀릴 수 있습니까?

예를 들어 ArrayResize와 ArrayInitialize 가 섞여 있습니다. 또는 예를 들어 표시기가 OnInit에서 버퍼를 ArrayInitialize하여 버퍼가 초기화된 것으로 잘못 생각합니다.

 
fxsaber :

예를 들어 ArrayResize와 ArrayInitialize가 섞여 있습니다.

글쎄, 그건 어린애 같은 실수야. 그것을 찾기 위해 노력할 가치가 있습니까?

 
Ilya Malev :

글쎄, 그건 어린애 같은 실수야. 그것을 찾기 위해 노력할 가치가 있습니까?

오류를 찾는 데는 노력이 필요합니다. 특히 코드가 크고 자신의 것이 아닌 경우.