Some double values invisible during cycle?

 

I am having a problem where double values are seemingly being ignored during the execution of a cycle.

I have tried many ways to fix it, but I just can't see a solution. Can anybody else see what is wrong here? Am I going crazy?!?

This is a simplified version of a piece of the code. (It has been cut down and is presented as a script because I thought that simplifying it might remove the problem, but the problem is still there).

//+------------------------------------------------------------------+
//|                                            Cycle Test Script.mq4 |
//+------------------------------------------------------------------+

double P;
int S;

int start()
  {
//----
   
while ( P <= 0.0010 )
      {  
   
      S = 200;
   
      if (P == 0.0001){S = 1;}          
      if (P == 0.0002){S = 2;}   
      if (P == 0.0003){S = 3;}
      if (P == 0.0004){S = 4;}   
      if (P == 0.0005){S = 5;} 
      if (P == 0.0006){S = 6;} 
      if (P == 0.0007){S = 7;} 
      if (P == 0.0008){S = 8;} 
      if (P == 0.0009){S = 9;} 
      if (P == 0.0010){S = 10;}
  
      Print("P = "+P+", S = "+S);  
  
      P += 0.0001;
      } 
   
//----
   return(0);
  }
//+------------------------------------------------------------------+

This should start with P having a value of 0 and then cycle through and increase the value of P by 0.0001 every time, until P is equal to 0.0010.

Each time it checks the value of P during the cycle, and gives S a value according to the value of P. (In this simplified example the value of S is directly related to P to make it easier to follow).

Then it prints the value of P and S in the Experts tab so that you can manually verify whether it is working.

At the start of every cycle the value of S is reset to the "default" setting of 200. Therefore, if one of the conditionals along the way is not triggered then the value of S should still be 200 by the time it is printed at the end of the cycle.

That way, a value of 200 for S should only be printed for the first cycle where the value of P is 0.

When I run the script it prints the following:

P = 0.00000000, S = 200

P = 0.00010000, S = 1

P = 0.00020000, S = 2

P = 0.00030000, S = 200

P = 0.00040000, S = 4

P = 0.00050000, S = 5

P = 0.00060000, S = 200

P = 0.00070000, S = 200

P = 0.00080000, S = 200

P = 0.00090000, S = 200

Clearly the value of S should be 3 when P = 0.0003, but it is printed as 200. This suggests that the conditional for if ( P == 0.0003) is not being triggered for some reason. The same for 7, 8 and 9.

The value of P is obviously changing, otherwise it would not be printed differently each time - but the conditionals are not responding to it. I left the double to be printed in full, in case it was a slight decimal place off (but it appears to be correct).

I thought perhaps that it was a problem with the printing or with the variable S, but the problem persists even if S is a string or a double and if if you use Comment(). The problem also occurs if S is introduced only during the cycle, and not at the start of the program.

Does anyone know what might be causing this. Am I being blind?

edit -

Also, I am a little confused as to why the last cycle (where P should equal 0.0010) is apparently not being run.

 

It's a double comparison issue . . . . read this thread: Can price != price ?

I get this result when I run a modified version of your code . . .

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: uninit reason 0

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00090000, S = 9

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00080000, S = 8

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00070000, S = 7

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00060000, S = 6

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00050000, S = 5

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00040000, S = 4

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00030000, S = 3

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00020000, S = 2

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00010000, S = 1

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: P = 0.00000000, S = 200

2012.07.22 16:04:16 Cycle Test Script EURUSD,H1: loaded successfully

 
clerin6:

edit -

Also, I am a little confused as to why the last cycle (where P should equal 0.0010) is apparently not being run.

It's also a double comparison issue . . use this line of code . . .

while ( P < 0.0011 )
 

Thanks. I would have been going round in circles for ever. I was following entirely the wrong track to find the solution there. My background is not in coding. I had no idea there could even be that type of problem with doubles.

You'd think that they would make that issue clearer - especially for a platform which is specifically designed to be comparing decimal places most of the time.

I just normalized all the doubles for now, and it works. Thanks. That even sorted the 10th cycle without needing to use < 0.0011.

I shall start implementing a function for comparing doubles in the future though, rather than relying on NormalizeDouble().

 
clerin6:

I shall start implementing a function for comparing doubles in the future though, rather than relying on NormalizeDouble().

I did this . . .

//+------------------------------------------------------------------+
//|                                            Cycle Test Script.mq4 |
//+------------------------------------------------------------------+

double P;
int S;

int start()
  {
//----
   
while ( P < 0.0011 )
      {  
   
      S = 200;
   
      if ( Flat(P) == Flat(0.0001) ){S = 1;}          
      if ( Flat(P) == Flat(0.0002) ){S = 2;}   
      if ( Flat(P) == Flat(0.0003) ){S = 3;}
      if ( Flat(P) == Flat(0.0004) ){S = 4;}   
      if ( Flat(P) == Flat(0.0005) ){S = 5;} 
      if ( Flat(P) == Flat(0.0006) ){S = 6;} 
      if ( Flat(P) == Flat(0.0007) ){S = 7;} 
      if ( Flat(P) == Flat(0.0008) ){S = 8;} 
      if ( Flat(P) == Flat(0.0009) ){S = 9;} 
      if ( Flat(P) == Flat(0.0010) ){S = 10;}
  
      Print("P = "+P+", S = "+S);  
  
      P += 0.0001;
      } 
   
//----
   return(0);
  }
//+------------------------------------------------------------------+


int Flat(double ValueToFlatten)
   {
   double Power = MathPow(10, Digits);
   int ReturnValue;
   
   ReturnValue = MathRound(Power * (ValueToFlatten + (4.9/ (Power*10) ) ) ) ;
   return (ReturnValue);
   
   }
 

So you end up comparing integers instead?

I'm guessing the 4.9 is there to make sure it is always rounded downwards, and the extra step with the Digits makes sure that you are always safe as long as you are using decimals no larger than that decimal place?

Great idea! Very useful, thanks for sharing :-)

 
clerin6:

1. So you end up comparing integers instead?

2. I'm guessing the 4.9 is there to make sure it is always rounded downwards, and the extra step with the Digits makes sure that you are always safe as long as you are using decimals no larger than that decimal place?

3. Great idea! Very useful, thanks for sharing :-)

1. Yep.

2. It was belt and braces to ensure that the value I was about to multiply and then round down as an integer started off being greater than the value I wanted to end up with, I wasn't sure if the double precision thing could end up with a value less or just greater . . . so could 12.00 actually be 11.99999999999999 ? so adding just under half a point means my value will always be above the value I want . . . I hope.

This solution fitted my code very well and kept it readable, there are other solutions that might work better with your code, that will be up to you to decide.

3. You are welcome.

 
P += 0.0001;

1/10 (and .0001) can not be exactly represented in floating point numbers. Therefor 0.1+0.1+0.1 != 0.3

Don't compare doubles with equality Can price != price ? - MQL4 forum

Reason: