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

 
fxsaber :

그것은 첫 번째 게시물부터 폐쇄되었습니다. 최소 숫자에 1보다 작은 값을 곱하면 결과는 0입니다.

올바른 코드는 어떻게 생겼습니까?

 // Неправильно написанная функция.
double WrongFunc( const double Num )
{
   return (Num ? 1 / ( 0.1 * Num) : 0 );
}
 
Igor Makanu :

올바른 코드는 어떻게 생겼습니까?

 
fxsaber :
 void OnStart ()
{
   double d = DBL_MIN - DBL_MIN / 10.0 ;
   Print (WrongFunc(d));
}
//_______________________________________________________________________
double WrongFunc( const double Num )
{
   return ( 0.1 * Num ? 1 / ( 0.1 * Num) : 0 );
}

컴파일: 부울이 아닌 표현식

결과: inf



내 의견으로는 최선의 선택이 아닙니다.

 
예, 문제가 없습니다
 bool IsNull( const double Num )
{
   return ( MathAbs (Num) < DBL_MIN );
}

double WrongFunc( const double Num )
{
   return (!IsNull( 0.1 * Num) ? 1 / ( 0.1 * Num) : 0 );
}


나는 그것을 스스로하지 않습니다.


추신: 미식가의 경우 적절한 연산자를 사용하여 DOUBLE 구조를 만들 수 있습니다. 그러나 이 모든 것은 연습과 거의 관련이 없습니다. 원래 사례 연구에서

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

mql5 언어의 특징, 미묘함 및 작업 방법

fxsaber , 2019.10.28 07:24

체크를 해도 0으로 나누는 방법.
 void OnStart ()
{  
   const double Profit = 100 ;
   const double Lots = 1 ;

   double TickValue[];  
   ArrayResize (TickValue, 1 );
  
   const double Points = TickValue[ 0 ] ? Profit / (Lots * TickValue[ 0 ] * _Point ) : 0 ; // zero divide     
}


오류는 분명합니다. 그러나 그러한 코드를 작성할 때 그러한 검사가 0으로 나누는 것을 피하기에 충분하지 않다는 것이 항상 분명한 것은 아닙니다.


생성된 배열 요소를 무효화하기만 하면 됩니다. 이 경우 충돌이 발생하는 것은 초기화가 없기 때문입니다. 그래서 그냥 초기화를 했습니다. 일반적인 견해에 신경쓰고 싶은 마음은 없습니다.

 
Igor Makanu :

컴파일: 부울이 아닌 표현식

결과: inf



내 의견으로는 최선의 선택이 아닙니다.

당신이 거기 아닌 어딘가에 있는 것.

 #define DBL_MIN_DENORM   4.94066 e- 324
   Print ( DBL_MAX * 1.1 ); // inf
   Print (DBL_MIN_DENORM* 0.5 ); // 0

여기에서 더 명확하지 않습니다. 어쨌든 0 으로 나누면 fpu 예외가 발생하는 이유입니다.

 
Vict :

당신이 거기 아닌 어딘가에 있는 것.

 void OnStart ()
{
   double Num= 0.0 ;
   if ( 0.1 * Num){} // expression not boolean     
}

fxsaber :
예, 문제가 없습니다

 bool IsNull( const double Num )
{
   return ( MathAbs (Num) < DBL_MIN );
}

 void OnStart ()
{
   union ULongTODouble {
       ulong ul;
       double d;
   } ULongDouble;

   ulong nan = 18446744073708624091 ;
   ULongDouble.ul = nan;
   double tst = DBL_MIN - DBL_MIN / 10000.0 ;
   Print (tst, " --> " ,IsNull(tst));
   tst = ULongDouble.d;
   Print (tst, " --> " ,IsNull(tst));
}
//_______________________________________________________________________

bool IsNull( const double Num )
{
   return ( MathAbs (Num) < DBL_MIN || Num!=Num );
}

2019.10.28 20:45:47.010 tst1 (EURUSD,H4) 2.224851351121351e-308 --> 참

2019.10.28 20:45:47.010 tst1 (EURUSD,H4) -nan --> 사실

상향:

정보 확인

 void OnStart ()
{
   double dev = 1.0 / 4.940656458412465 e- 324 ;
   Print ( "1. dev = " , dev, " ---> " , dev != dev);
   Print ( "2. dev = " , dev, " ---> " , IsInf(dev));
   dev = 1.0 / dev;

}
//+------------------------------------------------------------------+
bool IsInf( const double Num)
{
   return (Num > DBL_MAX || Num < DBL_MIN );
}
//+------------------------------------------------------------------+

2019.10.28 22:04:00.163 tst1 (EURUSD,H4) 1. dev = inf ---> 거짓

2019.10.28 22:04:00.163 tst1 (EURUSD,H4) 2. dev = inf ---> 참


저것들. 예상대로 inf는 NaN이 아닙니다.
 
fxsaber :
예, 문제가 없습니다
 bool IsNull( const double Num )
{
   return ( MathAbs (Num) < DBL_MIN );
}

googled "C++ 이중 0 나누기", 정규화되지 않은 숫자 는 코드에서 작동하지 않습니다. 다음을 수행해야 합니다.

 bool IsZerro( const double value )
{
   return (fabs( value ) * DBL_EPSILON == 0.0 );
}


명상을 위한 스크립트

 void OnStart ()
{
   union ULongTODouble {
       ulong ulong_;
       double double_;
   } ULongDouble;
   ulong i = 0 ;
   ulong count_NaN = 0 ;
   ulong count_Zerro = 0 ;
   double last_double = 0.0 ;
   while (i < ULONG_MAX ) {
      ULongDouble.ulong_ = i;
       double double_result = ULongDouble.double_;
       if (IsNaN(double_result)) count_NaN++;
       else {
         if (IsZerro(double_result)) {
            count_Zerro++;
            last_double = double_result;
         }
      }
       if (i % 1000000000 == 0 ) Print ( "i = " , i, " , NaN = " , count_NaN, " , Zerro = " , count_Zerro, " , last_double = " , last_double);
      i++;
   }
   Print ( "NaN = " , count_NaN);
   Print ( "Zerro = " , count_Zerro);
}
//+------------------------------------------------------------------+
bool IsZerro( const double value)
{
   return ( fabs (value) * DBL_EPSILON == 0.0 );
}
//+------------------------------------------------------------------+
bool IsNaN( const double value)
{
   return (value != value);
}
//+------------------------------------------------------------------+
bool IsInf( const double value)
{
   return (value > DBL_MAX || value < DBL_MIN );
}
//+------------------------------------------------------------------+
bool IsEqual( const double value1, const double value2)
{
   return ( fabs (value1 - value2) <= DBL_EPSILON );
}
//+------------------------------------------------------------------+
 

흥미로운 주제. 여기에서 뭔가를 파헤쳤습니다. 그것은 이론에 관한 블록에서 특히 주목할 만하다.

 abs(u - v)/abs(u) <= epsilon
&& abs(u - v)/abs(v) <= epsilon; // (4) 
   abs(u - v)/abs(u) <= epsilon
|| abs(u - v)/abs(v) <= epsilon; // (5)

이러한 방식으로 모든 언더플로 및 오버플 로 조건을 안전하게 보호할 수 있습니다. 그러나 위의 방법은 v 또는 u 가 0일 때 작동하지 않습니다. 이러한 경우 솔루션은 다른 알고리즘(예: (1)) 에 의존하는 것입니다.

Floating point comparison - 1.71.0
  • www.boost.org
Unless specified otherwise, when a value of floating-point type is compared inside a assertion, operators , , etc. defined for this type are used. However for floating point type, in most cases what is needed is not an equality (or inequality), but a verification that two numbers are or . For that purpose, a parameter that will instruct the...
 
Igor Makanu :
 void OnStart ()
{
   double Num= 0.0 ;
   if ( 0.1 * Num){} // expression not boolean     
}

무엇을? 절대적으로 유효한 경우 바보 같은 경고만 표시됩니다.

부울 변환

정수, 부동 소수점 , 범위가 지정되지 않은 열거형, 포인터 및 멤버에 대한 포인터 형식의 prvalue는 bool 형식의 prvalue로 변환할 수 있습니다.

값 0(integral, floating-point 및 범위가 지정되지 않은 열거의 경우)과 null 포인터 및 null 포인터-멤버 값은 false 가 됩니다. 다른 모든 값은 true 가 됩니다.

일반적으로 IsEqual(), IsInf(), IsZerro()와 같은 작성은 완전한 무지입니다. 토론에 참여하지 않겠습니다.

 
Vict :

무엇을? 절대적으로 유효한 경우 바보 같은 경고만 표시됩니다.

일반적으로 IsEqual(), IsInf(), IsZerro()와 같은 작성은 완전한 무지입니다. 토론에 참여하지 않겠습니다.

IsInf() 및 IsNaN()이 작동 중입니다.

IsEqual() 및 IsZerro() 의심스러운, 일부 출처에서 "트릭을 위한 트릭"으로 Google 검색

사유: