Can price != price ? - page 7

 

WHRoeder: this code good (especially check "added" and "default")? It may also serve as an easy final-reference for those who visit this thread and just go the last page (as I did)

#define LT    0
#define GT    1
#define GTE   2
#define LTE   3
#define EQ    4
#define NEQ   5

bool doublecomp(double a,int type,double b){
  // See https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>Point/2.);
    case GT: return(a-b>Point/2.);
    case GTE: return(a-b>-Point); // Added
    case LTE: return(b-a>-Point); // Added
    case EQ: return(!(MathAbs(a-b)>Point/2.));
    case NEQ: return(MathAbs(a-b)>Point/2.);
    default: return(-1); // Added - needed to avoid compile error about not all control paths returning a value
  }
}
 

That code is not accurate.

How can if( !MathAbs( a - b ) > Point/2) be used to compare for equality? That would tell you 1.4999 == 1.5000

 
SDC: How can if( !MathAbs( a - b ) > Point/2) be used to compare for equality? That would tell you 1.4999 == 1.5000
  1. It doesn't
    if( ! (MathAbs( a     -  b    ) > Point/2) ) be used to compare for equality? That would tell you 1.4999 == 1.5000
    if( ! (MathAbs(1.4999 - 1.5000  > 0.00005  )
    if( ! (0.0001                   > 0.00005  )
    if( ! (true                                )
    if( false                                  ) 1.4999 is NOT equal to 1.5000
  2. And I had pointed out to Roel13 in a PM that the GEQ/LEQ must be -Point/2 but he didn't edit the post
  3. And as I previous posted, you only have to worry about such nonsense if the equality/non-equality is important. If you want to open above the high of a candle, does it matter if (because of rounding) that it might trigger at exactly the high? If no just use bid > high[].
 

I use

if(NormalizeDouble(price1-price2,Digits)==0)


or for doubles that arn't actual prices, a higher precision

if(NormalizeDouble(value1-value2,8)==0)
 
SDC: I use
if(NormalizeDouble(price1-price2,Digits)==0)
Read the very first post and you'll learn why that isn't a good idea.
 

Raptors post about this code

double TestValue = iClose(NULL, 0, 0);
   
if(TestValue != NormalizeDouble(TestValue, Digits) ) //not equal

 

So if you use,

double TestValue = iClose(NULL, 0, 0);

if(NormalizeDouble(TestValue - iClose(NULL,0,0),Digits)==0) // they are considered equal

 I have tested that method in a variety of ways I have not found a scenario where it would not return the expected or desired result.
 

Final code... Thanks WHRoeder

#define LT    0
#define GT    1
#define GTE   2
#define LTE   3
#define EQ    4
#define NEQ   5

bool ComparePrice(double a,int type,double b){
  // See https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>Point/2.);
    case GT: return(a-b>Point/2.);
    case GTE: return(a-b>-Point/2.);
    case LTE: return(b-a>-Point/2.);
    case EQ: return(!(MathAbs(a-b)>Point/2.));
    case NEQ: return(MathAbs(a-b)>Point/2.);
  }
  return(-1);
}


And, maybe a secondary function for comparing all other doubles that are not prices...

bool CompareNormal(double a,int type,double b){
  // With thanks https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>0.0000000000000000000000000000001);
    case GT: return(a-b>0.0000000000000000000000000000001);
    case LTE: return(b-a>-0.0000000000000000000000000000001);
    case GTE: return(a-b>-0.0000000000000000000000000000001);
    case EQ: return(!(MathAbs(a-b)>0.0000000000000000000000000000001));
    case NEQ: return(MathAbs(a-b)>0.0000000000000000000000000000001);
  }
  return(-1);
}


See also 'MQL4 Reference > Language Basics > Data Types > Real Types (double, float)' in regards using small number for comparision.

Maybe someone knows how to write 0.00...1 better in expon

 
Roel13: Maybe someone knows how to write 0.00...1 better in expon
// case LT: return(b-a>0.0000000000000000000000000000001);
// case LT: return(b-a>1.0e-30);
See Real Types (double, float) - MQL4 Documentation
Noted that the value of epsilon in the above example can not be less than the predefined constant DBL_EPSILON. The value of this constant is 2.2204460492503131e-016.
Again, none of this is necessary, except in the case where the equals/not equals is important. E.g. open above the previous high, you don't want to open at the high due to round off.
 

So there is something else interesting I found, potentially in connection with "// 0 compare doesn't need this function".

Maybe a bug only in the latest versions, not sure. Comparing with 0 no longer functions correctly. I had to resort to something unfriendly like;

outcome=(int(outcome*100)/100.0);    // Resolution 2 digits

Just to ensure that 0 values actually ended up as 0 values.

WHRoeder, thanks. More study needed :)

 

I think this topic is dealt with too much unnecessary complexity.

Try to make your programmer's life always as easy as possible. Write defines (or go ahead with methods if you really must) in those classes where you need your double comparisons:

// add more floating point zeros if you need a higher precision
#define isZero(x) (fabs(x) < 0.000000001)
#define isEqual(x,y) (fabs(x-y) < 0.000000001)

When you need to compare two doubles then use it in a condition like this:

if (isEqual(myFirstDouble, mySecondDouble))
{
  // first and second doubles are considered equal
  // do something
}

If you want to see if a double is zero (or very, very close to zero) use a condition like this:

if (isZero(myDouble))
{
  // myDouble is considered zero
  // do something
}


On a side note, since I see many posts talking about divisions:

With encapsulation we tend to forget about the costs of code that is "outsourced" to some utility methods. Remind yourself that divisions are computationally very expensive! Especially, once wrapped in nice utility methods somewhere in utility classes, we start to use them everywhere in indicators or EAs and have long forgotten what computational steps they perform. When using the strategy tester we pay a lot of unnecessary time for our sloppiness.

Rule of thumb: Additions and subtractions are much much faster than multiplications and divisions. The division operation takes the highest computation time. Optimize divisions - wherever possible! If the denominator is fix like in this loop...

for(int i=0; i < rates_total; i++)
{
    // ...
    double fraction = someNumeratorValue / 100;
    // ...
}

then replace the denominator x with its inverted value 1/x:

for(int i=0; i < rates_total; i++)
{
    // ...
    double fraction = 0.01 * someNumeratorValue; // replace a denominator with it's inverted value, if possible.
    // ...
}

Also, if the result of a division is always the same, then do the computation once and save the result in a variable so you can use it everywhere in your code (e.g. in loops):

double tradesPerDay = totalTradesPerYear/365;

for(int i=0; i < rates_total; i++)
{
    // use precomputed tradesPerDay rather than computing the division here.
}

Cheers,

A.T.