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

 
amrali #:

As long as the two amounts are equal, any one of them is a valid minimum. Consider MathMin(1, 1), it does not differ if the function returns the first (1) or second (1).

So, returning 0.0 is not different from -0.0.

Edit: by the way, the two highlighted expressions are NOT identical.

I think I agree with my colleague amrali. I would also add that there is a native function MathMin(). It also thinks that zeros with different signs are equal. As far as I understand, its algorithm is quite simple. I duplicated it in my CustomMathMin() function.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
   {
   double positive_zero_val, negative_zero_val;
   positive_zero_val = 0.0;
   negative_zero_val = -0.0;
   // 1) -0.0 / 0.0
   double native_min_val, custom_min_val;
   native_min_val = ::MathMin(negative_zero_val, positive_zero_val);
   custom_min_val = CustomMathMin(negative_zero_val, positive_zero_val);
   ::Print("\nArguments: -0.0, 0.0");
   ::PrintFormat("Native min value = %0.2f", native_min_val);
   ::PrintFormat("Custom min value = %0.2f", custom_min_val);
   // 2) 0.0 / -0.0
   native_min_val = ::MathMin(positive_zero_val, negative_zero_val);
   custom_min_val = CustomMathMin(positive_zero_val, negative_zero_val);
   ::Print("\nArguments: 0.0, -0.0");
   ::PrintFormat("Native min value = %0.2f", native_min_val);
   ::PrintFormat("Custom min value = %0.2f", custom_min_val);
   }
//+------------------------------------------------------------------+
//| Custom MathMin                                                   |
//+------------------------------------------------------------------+
double CustomMathMin(double  value1, double  value2)
   {
   if(value1 < value2)
      return value1;
   return value2;
   }
//+------------------------------------------------------------------+


We have it in the log:

2024.01.29 23:49:46.351 c11 (EURUSD,H1) Arguments: -0.0, 0.0
2024.01.29 23:49:46.351 c11 (EURUSD,H1) Native min value = 0.00
2024.01.29 23:49:46.351 c11 (EURUSD,H1) Custom min value = 0.00
2024.01.29 23:49:46.351 c11 (EURUSD,H1) 
2024.01.29 23:49:46.351 c11 (EURUSD,H1) Arguments: 0.0, -0.0
2024.01.29 23:49:46.351 c11 (EURUSD,H1) Native min value = -0.00
2024.01.29 23:49:46.351 c11 (EURUSD,H1) Custom min value = -0.00


It is easy to see that from two equal numbers, the algorithm will take the second number as the minimum value of...

Документация по MQL5: Математические функции / MathMin
Документация по MQL5: Математические функции / MathMin
  • www.mql5.com
MathMin - Математические функции - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
fxsaber #:

You refuse to understand.

   Print(-0.0<0.0);     // false
   Print(-0.0>0.0);     // false
   Print(-0.0<=0.0);    // true
   Print(-0.0>=0.0);    // true
   Print(-0.0==0.0);    // true

it's nothing special. Just -0.0==0.0.

 
Nikolai Semko #:

nothing special. Just -0.0==0.0

I know the question very well, so I wrote both variants 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
}
 
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
}

So what is unusual?
The fact that in the numbers 0.0 and -0.0 not all 64 bits are the same is obvious:


but still 0.0 == -0.0

Base Convert: IEEE 754 Floating Point
  • baseconvert.com
Online IEEE 754 floating point converter and analysis. Convert between decimal, binary and hexadecimal
 
Ihor Herasko #:

The < and <= signs seem to be different.....

agree

 
Nikolai Semko # :

So what is unusual?
The fact that in the numbers 0.0 and -0.0 not all 64 bits are the same is obvious:



It expects MathMin() to be deterministic. So to always give the same result when the two arguments are the same. And not a different result depending on which argument is first or second.

fxsaber is right, this is a problem.

 
Alain Verleyen #:

It expects the MathMin() function to be deterministic. So to always give the same result when the two arguments are the same. And not a different result depending on which argument is first or second....

And it is. When 2 numbers are equal, the second one is returned. I have shown above with an example...

 
   Print(pow(0.0,0.0)); 	// 1.0
   Print(pow(-0.0,-0.0));       // 1.0
   Print(pow(-0.0,0.0));        // 1.0
   Print(pow(0.0,-0.0));        // 1.0
   Print(0.0*-0.0);             // -0.0
   Print(-0.0*-0.0);            // 0.0


and there's nothing wrong with that.

 
Alain Verleyen #:

It expects the MathMin() function to be deterministic. So to always give the same result when the two arguments are the same. And not a different result depending on which argument is first or second.

fxsaber is right, this is a problem.

You've got my point right. You can run into the hard-to-find issue of getting different results in large code. That's why I notified the community in this thread.

 
Alain Verleyen #:

It expects the MathMin() function to be deterministic. So to always give the same result when the two arguments are the same. And not a different result depending on which argument is first or second.

fxsaber is right, this is a problem.

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

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

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