MQL4 Conditional Double Relationship / Simple Double Arithmatic is intermittanatly broken with resultant "negative zero" "- 0" if ( a - b lessthan 0) where a==b

 
Was thread

Conditional Statement failure... [At wits end] if ( 1.4225 > 1.4225) is NOT TRUE!!!!!!

At the suggestion of AIS, I have changed all my double comparisons to format

   if ( double1 - double2 <relation> 0 ) 
      // Fails if double1 == double2

My EA obtains parameters from a custom indicator in order to make a dynamic stoploss decision.


Once the misinterpretation occurs it remains with in the function code block. I think this is more related to the compiler as other code blocks with similar double relationship code fragments do not fail.


Creating a test EA passes e.g.

int start()
   {
//---- 
   double   a = NormalizeDouble(a,Digits),
            b = NormalizeDouble(b,Digits),
            c;
   
   a = 1.42251;
   b = 1.42252;

   a = NormalizeDouble(a, Digits);
   b = NormalizeDouble(b, Digits);

   c = a - b;

   Print ("c = ", a, " - ", b);
   Print ("c = ", c, " as string ", DoubleToStr(c,Digits));

//---- done
   return(0);
   }

// OUTPUT
23:55:49 test EURUSD,H1: c = 1.4225 - 1.4225
23:55:49 test EURUSD,H1: c = 0 as string 0.0000

HOWEVER, in the code block we get a -0.0000

         trigger        = NormalizeDouble(iCustom(Symbol(), Period(), "Trigger", UPPER, 0),Digits);
         triggerAnchor  = NormalizeDouble(iCustom(Symbol(), Period(), "Trigger", UPPER, 1),Digits);

         double why     = trigger - triggerAnchor;
         Print("why ", why, " as string ", DoubleToStr(why,Digits));

         if ( trigger - triggerAnchor < 0 ) {
            text        = StringConcatenate("DynamicStoploss(): trigger ", trigger, "<", triggerAnchor, " triggerAnchor; ");
            _arrow      = Blue;
         }

// WHICH OUTPUTS

23:33:22 2008.09.15 21:24  Expert Advisor I EURUSD,H1: why -0 as string -0.0000
23:33:22 2008.09.15 21:24  Expert Advisor I EURUSD,H1: DEBUG_ORDERS: DynamicStoploss(): trigger 1.4225>1.4225 triggerAnchor; 

Here we have a resultant double -0

since -0 < 0 (go figure) my condition statement fails.

It is this corner case that makes me question that the " double rule" for conditional relationships has us subtract one double from another then compare to zero. As you see in my codes case I am intermittently out of luck.

 

This is a very old story.


Try to search forum for 'comparing doubles' or 'double compare'.

 

it is very important and critical issue. due to lack of debuger for MT4, it is so hard to be identified. I always found so many wireid things happened to my Ea, they didn't open a trade or close a trade at i expected point. this could be a cause.

how come if you want 4 digits precision but use NormalizeDouble( doubleNumbers,3) to compare them?

good luck.

 
Irtron:

This is a very old story.


Try to search forum for 'comparing doubles' or 'double compare'.

So far the most applicable solution seems to be article

Double Precision Math

https://forum.mql4.com/14834


However, Am I to understand that proving double arithmatic can return a "-0" is acceptable.


As a test engineer, I find this hard to stomach, the language should detect the -0 and return 0.


This "very old story", as Irton puts it, should end and be put to rest.


One other aspect of the debugger that would be nice to add an api for is to get real system clock time so we can get proper run time of code segments so we can see which workaround will be more appropriate.


My solution thus far has been to add a check for "-0.0000" NOTE that 0 != -0 either (BUG!!!)


double minus0 = double1 - double2;

if ( double1 - double2 < 0 && (DoubleToStr(minus0,5) != "0.00000") {code}


[precision 5 for Alpari, I suppose Digits would be acceptable for percision as well.]


A more effective way (after skimming articles) would be to convert the double to an "Un Normalized int which then could be relationally compared.

//+------------------------------------------------------------------+
//|                                         UnNormalizeDoubleInt.mq4 |
//|                  Copyright © 2009, Vampire Trading Network, Inc. |
//|                                 http://VampireTradingNetwork.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Vampire Trading Network, Inc."
#property link      "http://VampireTradingNetwork.com"

//+------------------------------------------------------------------+
//| UnNormalizeDoubleInt (double value, int precision)
//|
//|   Normalize a double value to specified precision Digits 
//|   Then Un Normalize the double to an integer for conditional
//|   relation arithmetic eliminating -0 Bug MQL4 Build 223 and earlier
//+------------------------------------------------------------------+
//| value      double   value to be normalized to a specific precision
//| precision  int      Digit precision to normalize the double value
//| 
//| return     double   an Un Normalized double representing the double
//|                     value as an Un Normalized Integer
//| 
//| Example:   
//|   value = 1.4225; 
//|   Print (UnNormalizeDoubleInt(value, 4)); 
//|   // Prints 14225 
//|   value = 1.4225; 
//|   Print (UnNormalizeDoubleInt(value, 3)); 
//|   // Prints 1423
//+------------------------------------------------------------------+
double      UnNormalizeDoubleInt (double value, int precision) {
   return (NormalizeDouble(value, precision) * MathPow(10, precision));
}
 

I agree with John. This may be an old problem that everybody knows about and is used to because it is common in other programming environments, but it's still a bug. I design computers for a living so please don't tell me these kinds of things can't be fixed - I know better. I hope that someone's watching all these posts that come up on this topic and thinking about how to fix it the next time around.

My two cents...

- Tovan