Substraction error... Digits doesn't work right... - page 2

 

so you couldn't solve this with google and all leads you got?
have you tried hard enough?

   double a = 1.37674;
   double b = 1.3761;
   double c = a - b;
   double d = 0.00064;
   //int digits = _Digits;
   int digits = 5;
   Print (c, "=", d);
   Print(NormalizeDouble(c, digits), "=", NormalizeDouble(d, digits));
   Print(DoubleToString(c, digits), "=", DoubleToString(d, digits));

   //int cPoints = (int) (c / _Point);
   int cPoints = (int) (c / 0.00001);
   int cPoints2 = (int) (NormalizeDouble(c, digits) / 0.00001);
   Print(cPoints);
   Print(cPoints2);       

 output:

0.0006399999999999739=0.0006400000000000001
0.0006400000000000001=0.0006400000000000001
0.00064=0.00064                            
63                                         
64                                         
 
n-v:

Ok, I know why it is happening, but I'm asking - do You know how to make it work?


 It does work.

To be honest, I don't totally understand it, but I accept that this is the way it has to be. 

We calculate a value and see it as  0.00064, but the program calculates a slightly different value at times because of the way that it works with doubles.

All we need to know is that once a value has been calculated and normalized it will be accepted

and never check for equality, but check for a difference of less than Point 

 
graziani:


I think that I didn't explain exactly what I'm doing and why... I wanted to test a strategy, where difference between 2 BIDs I will use for stop loss. So stop loss has to be in format double with 5 digits.
Really thanks for Your job, but:

0.0006399999999999739=0.0006400000000000001	
0.0006400000000000001=0.0006400000000000001
0.00064=0.00064                            	// it has 5 digits, but it's string and I need double value.
63                                         	
64    						// it's an integer. even divided by 100000 = 0.0006400000000000001




All was working fine until when 

double a = 1.37674;
double b = 1.3761;

because c = a - b is not equal to 0.00064 but... And here I could repeat the whole post.

I will only write this:

Can anyone divide:

double x = 64.0/100000;  // x = 0.0006400000000000001

call function whatever... or use command whatever, or do whatever to...

Print (x);  where in output x would be = 0.00064 but in DOUBLE format, not string...?


 

 

Have you read the mt4 reference of mt4 acc. to NormalizeDouble()?

You might have detected the example there:

   double pi=M_PI;
   Print("pi = ",DoubleToString(pi,16));
      
   double pi_3=NormalizeDouble(M_PI,3);
   Print("NormalizeDouble(pi,3) = ",DoubleToString(pi_3,16))
   ;
   double pi_8=NormalizeDouble(M_PI,8);
   Print("NormalizeDouble(pi,8) = ",DoubleToString(pi_8,16));
   
   double pi_0=NormalizeDouble(M_PI,0);
   Print("NormalizeDouble(pi,0) = ",DoubleToString(pi_0,16));
/*
   Result:
   pi= 3.1415926535897931
   NormalizeDouble(pi,3)= 3.1419999999999999
   NormalizeDouble(pi,8)= 3.1415926499999998
   NormalizeDouble(pi,0)= 3.0000000000000000
*/

NormalizeDouble() seems to be just the wrong functions fro you! I would suggest you to use MathRound instead like

double b = Bid,
       a = Ask,
       s = MathRound((Ask-Bid)/Point)*Point;
Comment(s);

(I know it looks a bit like what we say in German: From the back through the breast into your eye.)


 
graziani:

so you couldn't solve this with google and all leads you got?
have you tried hard enough?

 output:

 

I think the OP was asking how to end up with excatly 0.00064 without converting to string and back.

The cause of the error is difficult to understand it has something to do with the way 0.1 does not do right in binary. I think it is similar to the way one third does not do right in decimal it has to be rounded off.

 

graziani:

 This happens because of the floating-point format.

WHRoeder:
  1. Because some values (like 1./10.) can not be exactly represented Double-precision floating-point format - Wikipedia, the free encyclopedia
double d = 0.00064;
Print (d);
output:
0.0006400000000000001

This is the only way you can store 0.00064 in double or float type of variable.

In your case, you had an error because you tried to use the value without normalizing.

Proper way:

   int ticket = OrderSend(Symbol(), OP_SELL, lotSize, Bid, slippage, NormalizeDouble(Bid + 100 * _Points, _Digits), NormalizeDouble(Bid - 100 * _Points, _Digits), comment, magic, 0, clrRed);
 
//expected result 
   double x = 0.00064;
    
   double a = 1.37674;
   double b = 1.37610;

//calculate
   double c = a-b;

//test for accuracy
   double d = c-x;
   
   Print(c);
   Print(d);

//unacceptable Output
   0.0006399999999999739
  -2.612927235690066e-017


It seems kinda funny that in the 21century we are all using computers that can't do a simple floating point calculation accurately in decimal.

What you can do to avoid error accumulation is cast them to integer then back to double at the end. You can see from the accuracy test that way creates no actual error.

   int digits = 5;

//expected result
   double x = 0.00064;

//multiplier to integer
   double m = MathPow(10,digits);

   double a = 1.37674;
   double b = 1.37610;
  
//cast them to integer
   int c = int(a*m); 
   int d = int(b*m);

//calculate
   int e = c-d;
   
//convert it back to double
   double f = e/m;

//test for accuracy
   double g = f-x;
   
   Print(f);
   Print(g);

//acceptable output
   0.0006400000000000001
   0.0
 
graziani, You just killed me with that!!!:
double d = 0.00064;
Print (d);

output:
0.0006400000000000001

Plus what SDC has written... (I'm putting it here with small change, so maybe someone who will have similar problem could find it)
   double a = 1.37674;
   double b = 1.3761;
   double c = a - b;    // in decimal (human) system, it should be 0.00064
   double d = 0.00064;  // as I write it, it's ok, but look at output...
   double e = NormalizeDouble (c,Digits);   // Digits = 5; 
   double f = d - e;
   Alert ("a = ",a,", b = ",b,", c = ",c,", d = ",d,", e = ",e,", f = ",f);
output:
a = 1.37674, b = 1.3761, c = 0.0006399999999999739, d = 0.0006400000000000001, e = 0.0006400000000000001, f = 0.0   // f is correct!!!!!



Now I get it all - I was so sure, that everything I made is as it should be (I checked it 20, 30 times...), but I missed that one of my call function didn't have NormalizeDouble ().
All what I saw was: 

Print (x);

output:
0.0006400000000000001

And I thought that it is the reason why my program doesn't work as it should.



Guys - thanks for Your time, without You I wouldn't find it at all!! :D

 

I never realized it was this bad to do floating point calculations ...

//---expected result
   double x = 1.894531914;
//---

   double a = 1.37674;
   double b = 1.37610;
   
   double ab = a*b;
  
//test for accuracy
   double c = ab-x;
   
   Print("x = ",x);
   Print("ab= ",ab);
   Print("c = ",c);

//output
   x = 1.894531914
   ab= 1.894531914
   c = 2.220446049250313e-016 //oh dear ...
Reason: