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

 
Alexey Viktorov:

Просто не надо надеяться, что если отсутствует значение, то это обязательно 0 и соответственно false если это переменная не типа bool. Даже явное приведение к типу bool не спасёт.

Так работает без ошибок.

Я, честно говоря, вообще не понял откуда берётся ноль:

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

В TickValue[0] содержится мусор. Он может равняться нулю, и может не равняться нулю.

Если мусор в TickValue[0] не равен нулю, то рассчитываем Points = Profit / Lots * ненулевой мусор * _Point, иначе, если мусор в TickValue[0] равен нулю - Points приравниваем к нулю.

И откуда в выражении Lots * ненулевой мусор * _Point берётся ноль, если Lots инициализирован единицей при объявлении? В _Point ноль?

 
fxsaber:

Ошибка понятна по факту.

Ок, ошибка непонятна. И у меня не воспроизводится.

 
TheXpert:

Ок, ошибка непонятна. И у меня не воспроизводится.

Грубо говоря, вызов этой функции может вызывать деление на ноль.

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


Столкнулся с проблемой на практике в библиотеке Report. Потом понял, что это логично.

 
fxsaber:

Грубо говоря, вызов этой функции может вызывать деление на ноль.

у меня такой код на пограничных даблах выдает inf, но не крешится

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

void OnStart()
{
  Print(f(1e-308));  // 2019.10.28 13:02:19.457	test (USDJPY,H1) inf
}
 
TheXpert:

у меня такой код на пограничных даблах выдает inf, но не крешится

#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

void OnStart()
{
  double Num = 0;
  
  _W(Num) = (uchar)2;
  
  Print(WrongFunc(Num));
}
 
fxsaber:
такой крешится.
 
TheXpert:
такой крешится.

Подводя итог, перемножение двух ненулевых даблов может давать ноль. И это не не какой-то вырожденный случай, а реальный на практике.

Грубо говоря, боевой советник может сломаться из-за этого с далеко не нулевой вероятностью.

 
Причем проверка на ноль не спасет, ни явная, ни неявная (приведение к bool)
 
TheXpert:
Причем проверка на ноль не спасет, ни явная, ни неявная (приведение к bool)
  return(0.1 * Num ? 1 / (0.1 * Num) : 0);
 
fxsaber:

Подводя итог, перемножение двух ненулевых даблов может давать ноль. И это не не какой-то вырожденный случай, а реальный на практике.

Грубо говоря, боевой советник может сломаться из-за этого с далеко не нулевой вероятностью.

на NaN нужно дополнительно проверять, скорее всего этот код будет работать http://qaru.site/questions/20557/checking-if-a-double-or-float-is-nan-in-c

f != f

или ограничивать точность, как в примере CompareDoubles() - он кажется в СБ есть https://www.mql5.com/ru/docs/basis/types/double