есть ли константа для double NaN ?

 
есть ли константа для double NaN ?

 
DMITRII PECHERITSA:
есть ли константа для double NaN ?

Есть.

static Converter<ulong,double> NaNs;
static double inf = NaNs[0x7FF0000000000000];    // +infinity
                      // 0xFFF0000000000000         -infinity
static double nan = NaNs[0x7FF8000000000000];    // quiet NaN
static double nanind = NaNs[0xFFF8000000000000]; // -nan(ind)

Получить можно с помощью прилагаемого конвертера.

Файлы:
NaNs.mqh  2 kb
 

Смотрите  примеры для https://www.mql5.com/ru/docs/math/mathclassify

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
 {
//--- test NaN
  double nan=double("nan");
  PrintFormat("Test NaN: %G is %s, MathIsValidNumber(NaN)=%s",
              nan,
              EnumToString(MathClassify(nan)),
              (string)MathIsValidNumber(nan));
//--- test infinity
  double inf=double("inf");
  PrintFormat("Test Inf: %G is %s, MathIsValidNumber(inf)=%s",
              inf,
              EnumToString(MathClassify(inf)),
              (string)MathIsValidNumber(inf));
//--- test normal value
  double normal=1.2345e6;
  PrintFormat("Test Normal: %G is %s, MathIsValidNumber(normal)=%s",
              normal,
              EnumToString(MathClassify(normal)),
              (string)MathIsValidNumber(normal));
//--- test subnormal value
  double sub_normal=DBL_MIN/2.0;
  PrintFormat("Test Subnormal: %G is %s, MathIsValidNumber(sub_normal)=%s",
              sub_normal,
              EnumToString(MathClassify(sub_normal)),
              (string)MathIsValidNumber(sub_normal));
//--- test zero value
  double zero=0.0/(-1);
  PrintFormat("Test Zero: %G is %s, MathIsValidNumber(zero)=%s",
              zero,
              EnumToString(MathClassify(zero)),
              (string)MathIsValidNumber(zero));
 } 
 /*
 Результат:
   Test NaN: NAN is FP_NAN, MathIsValidNumber(NaN)=false
   Test Inf: INF is FP_INFINITE, MathIsValidNumber(inf)=false
   Test Normal: 1.2345E+06 is FP_NORMAL, MathIsValidNumber(normal)=true
   Test Subnormal: 1.11254E-308 is FP_SUBNORMAL, MathIsValidNumber(sub_normal)=true
   Test Zero: -0 is FP_ZERO, MathIsValidNumber(zero)=true
*/ 
//+------------------------------------------------------------------+
Документация по MQL5: Математические функции / MathClassify
Документация по MQL5: Математические функции / MathClassify
  • www.mql5.com
//| Script program start function                                    |
 
   int hash_a,hash_b;
   hash_b=hash_a&0x7FFFFFFF;
   как работает понятно, но в чём смысл данной конструкции? 

 
DMITRII PECHERITSA:
   как работает понятно, но в чём смысл данной конструкции? 

Читай стандарты) Или, хотя бы, википедию)
 

   Нашел хорошее объяснение на stackoverflow. Если кому-то лень искать, вот перевод:

   Постоянная 0x7FFFFFFF представляет собой 32-битное целое число в шестнадцатеричном формате со всеми установленными битами, кроме самого высокого.

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

   Когда вы используете % для отрицательного значения, вы получаете отрицательное значение. Нет отрицательных сегментов, поэтому, чтобы избежать этого, вы можете удалить знаковый бит (самый высокий бит) и один из способов сделать это - использовать маску, например. x & 0x7FFFFFFF который сохраняет все биты, кроме верхнего. Другой способ сделать это - сдвиг x >>> 1, однако, это медленнее.

   Немного лучший подход - «взять модуль и применить Math.abs». При этом используются все биты хэш-кода, что может быть лучше.

 
Может пригодится.
Для проверки , что переменная double стала NaN, достаточно сравнить её с собой. При NaN она не равна себе.
 
DMITRII PECHERITSA:

   Нашел хорошее объяснение на stackoverflow. Если кому-то лень искать, вот перевод:

   Постоянная 0x7FFFFFFF представляет собой 32-битное целое число в шестнадцатеричном формате со всеми установленными битами, кроме самого высокого.

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

   Когда вы используете % для отрицательного значения, вы получаете отрицательное значение. Нет отрицательных сегментов, поэтому, чтобы избежать этого, вы можете удалить знаковый бит (самый высокий бит) и один из способов сделать это - использовать маску, например. x & 0x7FFFFFFF который сохраняет все биты, кроме верхнего. Другой способ сделать это - сдвиг x >>> 1, однако, это медленнее.

   Немного лучший подход - «взять модуль и применить Math.abs». При этом используются все биты хэш-кода, что может быть лучше.

Наверное неправильно, т.к. потеряется младший бит

 
Nikolai Semko:
Может пригодится.
Для проверки , что переменная double стала NaN, достаточно сравнить её с собой. При NaN она не равна себе.

Опасный трюк, т.к. работает только при точной модели FP математики, более медленной - в нативе, все сравнения FP  генерируют 2 условных перехода, по Nan и непосредственно само условие.

В быстрой модели FP математики, первую проверку опускают, в итоге нарушается условие Nan != Nan, более того, Nan удовлетворяет и другие условия сравнения с нормальными числами!


настройки C++ проекта


С++ код

int main(void)
  {
   double x=0;
   double y=M_PI;

   (INT64 &)x=0x7FFF000000000000;

   printf("%i %i %i %i\n",x==x,x==y,x>y,x<y);
   
   return(0);
  }


вывод

1 1 0 1


Не исключено, что мы тоже добавим режим быстрой математики, тогда при его использовании часть вашего кода будет работать некорректно!

 
Ilyas:

Опасный трюк, т.к. работает только при точной модели FP математики, более медленной - в нативе, все сравнения FP  генерируют 2 условных перехода, по Nan и непосредственно само условие.

В быстрой модели FP математики, первую проверку опускают, в итоге нарушается условие Nan != Nan, более того, Nan удовлетворяет и другие условия сравнения с нормальными числами!


настройки C++ проекта


С++ код


вывод


Не исключено, что мы тоже добавим режим быстрой математики, тогда при его использовании часть вашего кода будет работать некорректно!

Понял.
Спасибо, - не знал.
И спасибо за предупреждение. 
Пожалуйста, предупредите, когда добавите быструю математику.


а пока работает так:

void OnStart() {
   union DLB_LONG {
      double d;
      long l;
   };
   DLB_LONG x;
   double y=M_PI;
   x.l=0x7FFF000000000000;
   printf("%i %i %i %i\n",x.d==x.d,x.d==y,x.d>y,x.d<y);   // 0 0 0 0
}
Причина обращения: