Features of the mql5 language, subtleties and tricks - page 242

 

an old feature of Min/Max in MQL - they work the way the developers think, i.e. correctly :-)

it's the standards that are wrong.

 
Nikolai Semko #:

ahhh..., then why was it so confusing about " Mathematically the same expression (highlighted) " and union
was enough:

but since 0.0 == -0.0, then I can't imagine a situation where this could be a problem and, in fact, affect anything at all

If it wasn't zero, then it would be a problem. And at zero it doesn't affect anything.
For:

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




So, all you need to know is that 0 = -0
That's the whole feature that doesn't affect calculations and logic

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 #:

I have an excellent understanding of the question, so I wrote both versions of MathMin to show that mathematically identical functions in programming languages produce different results.

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
}

It seems to be a bug.

It works fine in C++:

#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();
}

in the console:

Long negative zero = 0


Question in passing to the developers. Is it normal that in the debugging window the Union variable does not expand and does not react at all to a click?


The fields Union.Num1 and Union.Num2 were added manually. At least this way you can see the values...

 
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 #:

It seems to be a bug.

It works fine in C++:

in the console:

there is no bug. In C++ it is the same.
you just made a mistake with formatting and type

try this:

#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 = %ll d", 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 #:

there is no bug. It is the same in C++.
just made a mistake with formatting and type

try this:

Yes, I was in a hurry. Thanks for the science ))

 

Sometimes you need to quickly put an EA into the Tester. You can do it like this.

Select a date in the future and press CTRL+F5 in ME.

 
If you need fast compilation without a big performance hit, you can use compiled libraries - #import .ex5
Reason: