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

 
Alain Verleyen #:

Он ожидает, что функция MathMin() будет детерминированной. Таким образом, чтобы всегда давать один и тот же результат, когда два аргумента одинаковы. И не разный результат в зависимости от того, какой аргумент первый или второй.

fxsaber прав, это проблема.

аaa..., тогда зачем так было запутывать про " Математически одинаковое выражение (выделено) " и union
достаточно было:

Print(MathMin(-0.0, 0.0)); // 0.0
Print(MathMin(0.0, -0.0)); // -0.0

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

 

старинная особенность Min/Max в MQL - они работают так как считают разработчики, то есть верно :-)

это стандарты ошибаются

 
Nikolai Semko #:

аaa..., тогда зачем так было запутывать про " Математически одинаковое выражение (выделено) " и union
достаточно было:

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

если бы это был не ноль, тогда это была бы проблема. А при нуле ни на что не влияет.
Ибо:

x * 0.0 = 0.0
x * -0.0 = -0.0
x + -0.0 = x
x - -0.0 = x
pow(x,-0.0) = 1
log(0.0)  // -inf
log(-0.0)  // -inf
 

c++ - What is the difference between -0 and 0? - Stack Overflow




Поэтому, все что нужно знать, это то, что 0 = -0
Вот и вся особенность, которая не влияет на вычисления и логику

What is the difference between -0 and 0?
What is the difference between -0 and 0?
  • 2010.09.14
  • Danvil Danvil 22.5k 20 20 gold badges 66 66 silver badges 90 90 bronze badges
  • stackoverflow.com
In C++, for example returns . The expression is true, but the bits are different. What is the purpose of having something like which should be but is represented differently? Is used exactly the same way as in any computations?
 
fxsaber #:

Отлично разбираюсь в вопросе, поэтому написал оба варианта MathMin, чтобы показать, что математически одинаковые функции в языках программирования выдают неодинаковые результаты.

template <typename T>
T ToType( const double Num )
{
  union UNION
  {
    T Num1;
    double Num2;
  } Union;
  
  Union.Num2 = Num;
  
  return(Union.Num1);
}

void OnStart()
{
  Print(ToType<long>(MathMin(-0.0, 0.0))); // 0
  Print(ToType<long>(MathMin(0.0, -0.0))); // -9223372036854775808
}

Кажись баг.

На С++ работает нормально:

#include <iostream>

using namespace std;
//
template <typename T>
T ToType(const double Num)
{
    union UNION
    {
        T Num1;
        double Num2;
    } Union;
    Union.Num2 = Num;
    return(Union.Num1);
}
//
int main()
{
    double positive_zero_val, negative_zero_val;
    positive_zero_val = 0.0;
    negative_zero_val = -0.0;
    //---
    long long_negative_zero_val = ToType<long>(negative_zero_val);
    printf("\nLong negative zero = %d", long_negative_zero_val);
    cin.get();
}

в консоли:

Long negative zero = 0


Вопрос попутно к разработчикам. Это нормально, что в окне отладки переменная Union не разварачивается и совсем не реагирует на клик?


Вручную добавлены поля Union.Num1 и Union.Num2. Хотя бы так видны значения...

 
string DoubleToHexadecimal(const double value)
  {
   return StringFormat("0x%.16llX", value);
  }

void OnStart()
  {
   Print(DoubleToHexadecimal(0.0) );    // 0x0000000000000000   (i.e, long integer 0)
   Print(DoubleToHexadecimal(-0.0) );   // 0x8000000000000000   (i,e, LONG_MIN -9223372036854775808)
  }
  

Works as expected! The first bit (bit index 0) is the sign bit which is set for -0.0.

These are also more special cases in ieee 754 format. https://www.wikiwand.com/en/IEEE%20754#Special_values

void OnStart()
  {
   const double Nan = (double)"nan";
   const double Inf = (double)"inf";

   Print( MathMin(Nan, Inf));   // inf
   Print( MathMin(Inf, Nan));   // nan

   Print( MathMin(Nan, 0));     // 0.0
   Print( MathMin(0, Nan));     // nan
  }
 
Denis Kirichenko #:

Кажись баг.

На С++ работает нормально:

в консоли:

нет никакого бага. В С++ тоже самое. 
просто ошиблись с форматированием и с типом

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

#include <iostream>

using namespace std;
//
template <typename T>
T ToType(const double Num)
{
    union UNION
    {
        T Num1;
        double Num2;
    } Union;
    Union.Num2 = Num;
    return(Union.Num1);
}
//
int main()
{
    double positive_zero_val, negative_zero_val;
    positive_zero_val = 0.0;
    negative_zero_val = -0.0;
    //---
    long long long_negative_zero_val = ToType<long long>(negative_zero_val);
    printf("\nLong negative zero = %lld", long_negative_zero_val);
}
 

In the same context, this can examine the 64 bit representation of doubles https://www.mql5.com/en/code/20822

//+------------------------------------------------------------------+
//| Returns the bit representation corresponding to a double value . |
//+------------------------------------------------------------------+
long DoubleToLongBits(const double value)
  {
   union _d {double value; long bits;} dbl;
   dbl.value = value;

   return dbl.bits;
  }

or the shorter version

long DoubleToLongBits(const double value)
  {
   union _d {double value; long bits;} dbl = { value };

   return dbl.bits;
  }
 
Nikolai Semko #:

нет никакого бага. В С++ тоже самое. 
просто ошиблись с форматированием и с типом

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

Да, я поторопился. Спасибо за науку ))

 

Иногда нужно быстро поместить советник в Тестер. Можно сделать так.

Выбрать дату в будущем и нажать CTRL+F5 в ME.

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