Особенности языка mql5, тонкости и приёмы работы - страница 144

 
Igor Makanu:

на NaN нужно дополнительно проверять

Там нормальное число. Проверка простая - на что делишь, то и проверяй на ноль.

 
fxsaber:

Там нормальное число. Проверка простая - на что делишь, то и проверяй на ноль.

но Вы не проверяете на ноль в этом коде:

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

выражение Num ?  в MQL будет истинно если в 8 байтах double не будет значения 0x0000000000000000

в любом другом случае это выражение (Num ?) будет true


я в начале месяца поднимал дискуссию насчет не строй проверки bool в MQL - ответ, потери данных нет, значит не нужно - это та же проблема, Вы иожете попытаться разделить выражение на NaN - байты же double будут не пустые?


сейчас не смогу проверить, но скорее всего нужно так:

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

но Вы не проверяете на ноль в этом коде:

сейчас не смогу проверить, но скорее всего нужно так:

Не будет работать. В примере краша 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 действительно работает, можно цикл и с нуля запустить, дольше ждать придется

тут в общем Ваш вопрос это вопрос точности double - она вообще привязана к конкретному типу процессора, поэтому и были выше комментарии, что не воспроизводится ошибка


UPD:

лучше так вывод сделать:

if(ULongDouble.d != ULongDouble.d) Print("NaN, d = ", ULongDouble.d); // tst1 (EURUSD,H1)	NaN, d = -nan
 
Хм, а нафига при делении на ноль даблов, исключение вообще выбрасывается? Ну была бы inf, что-то фигня какая-то.
 
Igor Makanu:

тут в общем Ваш вопрос это вопрос точности double - она вообще привязана к конкретному типу процессора, поэтому и были выше комментарии, что не воспроизводится ошибка

Воспроизводится на любом. Честно говоря, не понял, почему столько разговоров на эту тему. Ну перемножили два ненулевых числа, получив ноль. Никакой магии.


Такой код же все понимают?

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


Тут абсолютно аналогичная ситуация, когда d превращается в ноль.

 
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 true

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

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

2019.10.28 16:25:28.667 tst1 (EURUSD,H4) zero divide in 'tst1.mq5' (28,31)



fxsaber:

Тут абсолютно аналогичная ситуация, когда d превращается в ноль.

я про не ноль речь веду, в Вашем примере когда 0.1 * Num ?  это bool - то это тупо наличие хоть одного бита в 8 байтах double

а когда  0.1 * Num это double, то при потере точности можно вылететь в Nan и получить zero divide 

 
Вот этого не понял.
#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.

Думаю у второго числа невалидный double формат, но оно все равно валидируется и в принте и в операциях. возможно из-за этого и сыплется.

 
fxsaber:
Вот этого не понял.


DBL_MIN - не минимальный положительный double.

ну сравните DBL_MIN  с NaN - результат же в bool будет?

а если делить 1.0 на не число, то как выше сказали, то получим исключение

в общем то, что писали много раз разработчики, что сравнивать на больше/меньше/равно double не корректно - это правда, можно иногда на не число попасть и результат сравнения будет не предсказуемый

Причина обращения: