Bug in the new Build? --> comparing 2 doubles

 

Something really strange is going on here and I just don't get it.

...
double TrailingStop;
...

if (OrderStopLoss() < TrailingStop) {
	Log("StopLoss="+OrderStopLoss()+" TrailingStop="+TrailingStop);
	doStuff();
}


My log shows:

...
StopLoss=1.11190000 TrailingStop=1.11190000
...

--> wtf?


Same datatype. Same value. But still not the same???


Any help would be appreciated.

 
schnappi:

Something really strange is going on here and I just don't get it.

This is just about the most common question raised on this forum - it's to do with the nature of floating point arithmetic, and the need to use the NormalizeDouble() function when working with double values in many contexts. See topics such as 'Conditional Statement failure... [At wits end] if ( 1.4225 > 1.4225) is NOT TRUE!!!!!!' or https://forum.mql4.com/22227 or  'MQL4 MathCeil() intermittantly returns wrong result'.

 

You might find interest 'Conditional Statement failure... [At wits end] if ( 1.4225 > 1.4225) is NOT TRUE!!!!!!' here and is basis for my feeble understanding of what AIS on about.

Personally, I gave up chasing my tail and coded up a set of one line functions. Maybe many will laugh and shake heads with pity - not bothered anymore, so many things are loose that any old chewing gum is better than nothing, yes?

So, I present for readers amusement...

double normD (double dVal) {return(NormalizeDouble(dVal,Digits));}
//
//>=
bool isAgeB (double P1,double P2) {if(isAgtB(P1,P2))return(true);if(isAeqB(P1,P2))return(true);return(false);}
//bool isAgeB (double P1,double P2) {return(isAgtB(P1,P2)||isAeqB(P1,P2));}
//
//>
bool isAgtB (double P1,double P2) {return( normD( P1 - P2 ) > 0 );}
//
//==
bool isAeqB (double P1,double P2) {return( normD( P1 - P2 ) == 0 );}
//
//!=
bool isAneB (double P1,double P2) {return( normD( P1 - P2 ) != 0 );}
//
//<
bool isAltB (double P1,double P2) {return( normD( P1 - P2 ) < 0 );}
//
//<=
bool isAleB (double P1,double P2) {if(isAltB(P1,P2))return(true);if(isAeqB(P1,P2))return(true);return(false);}
//bool isAleB (double P1,double P2) {return(isAltB(P1,P2)||isAeqB(P1,P2));}

Reader corrections of course, requested ;-)

 
THANKS A LOT!
 
fbj:

You might find interest 'Conditional Statement failure... [At wits end] if ( 1.4225 > 1.4225) is NOT TRUE!!!!!!' here and is basis for my feeble understanding of what AIS on about.

Taking a concrete example from one of the topics linked to above,  0.56 / 0.01 =  56.000000000000007. Arguably, the real problem in MQL is that you can only display 8 digits of precision using things like DoubleToStr(). The actual value of the Trailingstop variable in schnappi's example is doubtless something like 1.111900000002


The Wikipedia article at https://en.wikipedia.org/wiki/Floating_point is also worth a read. Quoting from that:


Floating-point arithmetic is [...] at its worst when it is expected to model the interactions of quantities expressed as decimal strings that are expected to be exact. An example of the latter case is financial calculations. For this reason, financial software tends not to use a binary floating-point number representation.

We wait to see what happens in MT5...

 

jjc, once again - thanks for further illumination.

btw, you think I'm on ok track with my one liners ?

thx

 
fbj:

btw, you think I'm on ok track with my one liners ?

Looks fine to me, but I don't personally deal with the sort of system where you tend to get this kind of issue. It's also a matter of personal preference, and what you find most readable in your own code. You ought to be able to do normD(X) > normD(Y) as well as isAgtB(X, Y).


The real fun will come in MT5, which will doubtless have partial fills and therefore the potential for fractional prices. At which point, NormalizeDouble(X, Digits) potentially becomes inappropriate...

Reason: