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

 
Igor Makanu :

NaN의 경우 추가 확인이 필요합니다.

정상적인 숫자입니다. 확인은 간단합니다. 무엇으로 나눈 다음 0인지 확인합니다.

 
fxsaber :

정상적인 숫자입니다. 확인은 간단합니다. 무엇으로 나눈 다음 0인지 확인합니다.

하지만 이 코드에서는 null을 확인하지 않습니다.

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

표현식 번호 ? MQL에서는 8바이트 double에 0x00000000 00000000 값이 없으면 true가 됩니다.

다른 경우에는 이 표현식( Num ? )이 true가 됩니다.


월 초에 MQL의 잘못된 bool 검사에 대한 토론을 올렸습니다. 대답은 데이터 손실이 없으므로 필요하지 않다는 것입니다. 이것은 동일한 문제입니다. 표현식을 NaN으로 나눌 수 있습니다. 바이트가 비어 있지 않습니까?


지금은 테스트할 수 없지만 다음과 같이 보입니다.

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

하지만 이 코드에서는 null을 확인하지 않습니다.

지금은 테스트할 수 없지만 다음과 같이 보입니다.

작동 안 할 것이다. 충돌 예에서 Num은 일반 숫자입니다. bool은 폐업입니다.

 
fxsaber :

작동 안 할 것이다. 충돌 예에서 Num은 일반 숫자입니다. bool은 폐업입니다.

체크된 NaN 조회

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

   ulong i = 0xFFFFFFFFFFFFFFFF ;
   while (i > 0 && ! IsStopped ()) {
      ULongDouble.ul = i;
       if (ULongDouble.d != ULongDouble.d) Print ( "NaN, i = " , i);
      i--;
   }

}
//_______________________________________________________________________

그것은 MQL5에서 실제로 작동합니다. 처음부터 루프를 시작할 수 있습니다. 더 오래 기다려야 합니다.

여기에서 일반적으로 귀하의 질문은 이중 정확도에 대한 질문입니다. 일반적으로 특정 유형의 프로세서에 연결되어 있기 때문에 오류가 재현되지 않는다는 위의 의견이 있었습니다.


상향:

다음과 같이 결론을 내리는 것이 좋습니다.

 if (ULongDouble.d != ULongDouble.d) Print ( "NaN, d = " , ULongDouble.d); // tst1 (EURUSD,H1)	NaN, d = -nan
 
흠, 하지만 double을 0으로 나눌 때 예외가 전혀 발생하지 않는 이유는 무엇입니까? 글쎄, 그것은 일종의 쓰레기 같은 inf 일 것입니다.
 
Igor Makanu :

여기에서 일반적으로 귀하의 질문은 이중 정확도에 대한 질문입니다. 일반적으로 특정 유형의 프로세서에 연결되어 있기 때문에 오류가 재현되지 않는다는 위의 의견이 있었습니다.

어떤 경우에도 재현 가능합니다. 솔직히 말해서, 나는 이 주제에 대해 왜 그렇게 많은 대화가 있는지 이해하지 못합니다. 음, 우리는 0이 아닌 두 개의 숫자를 곱하여 0을 얻었습니다. 마법이 없습니다.


모두가 이 코드를 이해하고 있습니까?

 void OnStart ()
{
   double d = 0.5 ;  
   int Count = 1 ;
  
   while (d *= d)
    Count <<= 1 ;
    
   Print (Count);
}


d가 0이 될 때와 절대적으로 유사한 상황이 있습니다.

 
fxsaber :

마법이 없습니다.

그것은 다음과 같이 인쇄되는 마술입니다.

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

   ulong nan = 18446744073708624091 ;
   ULongDouble.ul = nan;
   
   Print ( "ULongDouble.d != ULongDouble.d " , ULongDouble.d != ULongDouble.d);
   double d_value = 0.1 * ULongDouble.d;
   bool b_value = d_value;
   Print ( "b_value =  " , b_value);
   Print ( "d_value =  " , d_value);
   Print ( "1 / d_value =  " , 1 / d_value);

}
//_______________________________________________________________________

2019.10.28 16:25:28.643 tst1 (EURUSD,H4) ULongDouble.d != ULongDouble.d 참

2019.10.28 16:25:28.643 tst1 (EURUSD,H4) b_value = 참

2019.10.28 16:25:28.643 tst1 (EURUSD,H4) d_value = 난

2019.10.28 16:25:28.667 tst1 (EURUSD,H4) 'tst1.mq5'의 0 나누기(28,31)



fxsaber :

d가 0이 될 때와 절대적으로 유사한 상황이 있습니다.

나는 0에 대해 말하는 것이 아닙니다. 귀하의 예에서 0.1 * Num ? 이것은 bool입니다 - 8 더블 바이트에 적어도 하나의 비트가 있다는 것은 어리석은 일입니다.

0.1 * Num이 double이면 정밀도 손실의 경우 Nan으로 날아가 0 나누기를 얻을 수 있습니다.

 
이것은 내가 이해하지 못한 것입니다.
 #include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

void OnStart ()
{
   double Num = 0 ;
  
  _W(Num) = ( uchar ) 1 ;
  
   Print (Num < DBL_MIN ); // true
   Print ( DBL_MIN );       // 2.225073858507201e-308
   Print (Num);           // 4.940656458412465e-324
}


DBL_MIN은 최소 양수 double이 아닙니다.

 
fxsaber :

DBL_MIN은 최소 양수 double이 아닙니다.

두 번째 숫자에 잘못된 이중 형식이 있다고 생각하지만 인쇄 및 작업 모두에서 여전히 유효성이 검사됩니다. 아마도 그것이 무너지는 이유일 것입니다.

 
fxsaber :
이것은 내가 이해하지 못한 것입니다.


DBL_MIN은 최소 양수 double이 아닙니다.

DBL_MIN 을 NaN과 잘 비교하십시오. 결과는 bool입니까?

1.0을 숫자가 아닌 것으로 나누면 위에서 언급한 것처럼 예외가 발생합니다.

일반적으로 개발자가 여러 번 쓴 내용, 더/적거나/같음을 두 배로 비교하는 것은 올바르지 않습니다. 이것은 사실입니다. 때로는 숫자가 아닌 것을 칠 수 있으며 비교 결과는 예측할 수 없습니다.