is this comparison safe for non constant data ? - page 2

 
amrali #:
Please explain it more. I could not understand it.

i mean the minimum possible deviation is a multiple of epsilon (or what's it called) ?

 
amrali #: Please explain it more. I could not understand it.

Did you miss the link in #2, or what was unclear?

 
Lorentzos Roussos #:

i mean the minimum possible deviation is a multiple of epsilon (or what's it called) ?

According to ieee-754 standard:

The floating-point result from basic math operators (+ - * /) may differ from the true real value by < 0.5 * DBL_EPSILON * true real value.  (DBL_EPSILON = 2^-52, which is approx. 2.22e-16)

"This means, the larger your numbers, the larger the absolute error will be."

So, for comparing double numbers like forex prices around 1.0, use a small epsilon like 1e-12. To handle comparison of larger numbers like volumes (tens or hundreds), you can use a larger epsilon like 1e-10 or 1e-8 to be on the safe side. These numbers represents the maximum expected calculation (round-off) errors that can be encountered based on the magnitude of the numbers.

This is an inherent feature (or bug!) in floating-point numbers as it works in binary bits 0 and 1, not in decimals 0 to 9 like humans. This is called the round-off error after performing math operations.


For example, the fp result of 0.1 + 0.2 may differ from the true real result 0.3 by a very tiny amount.

This can be explained as:

void OnStart()
  {
  Print(0.1 + 0.2);  // 0.30000000000000004
  Print(0.3);        // 0.3
  }

Although the literal 0.3 is represented exactly as double, 0.1+0.2 is not exactly equal to 0.3, because a round-off error was introduced (its magnitude can be calculated as discussed above) during the math calculation.

So, any difference that is larger than those tiny calculation errors is considered a true difference, rather than a calculation (round off) error. For example if you compare your calculated SL (0.1+0.2) to the stoploss price (0.3) on the server (in order to move your trailing stop), do not use  == != >= <= > < because there may be a tiny error in your calculation, which you should omit or handle when comparing doubles. (for example, use the comparison macros in post #6)

This is also another method to check for equality, which scales the epsilon (max. roundoff) to the magnitude of the numbers, dynamically:

bool EqualDoubles(double a, double b)
  {
   return (a == b) || MathAbs(a - b) <= DBL_EPSILON * MathMax(MathAbs(a), MathAbs(b));
  }

void OnStart()
  {
  Print(0.1 + 0.2);  // 0.30000000000000004
  Print(0.3);        // 0.3

  Print( 0.3 == 0.1 + 0.2 );              // false
  Print( EqualDoubles(0.3, 0.1 + 0.2) );  // true
  }


Edited:

For better handling of roundoffs after a series of math calculations, we can use a less tight epsilon

bool EqualDoubles(double a, double b)
  {
   return (a == b) || MathAbs(a - b) <= 10 * DBL_EPSILON * MathMax(MathAbs(a), MathAbs(b));
  }
 
William Roeder #:

Did you miss the link in #2, or what was unclear?

Thanks William for the link, but I did not find there any method of choosing the "optimal" epsilon for comparing doubles.
 
amrali #:

According to ieee-754 standard:

The floating-point result from basic math operators (+ - * /) may differ from the true real value by < 0.5 * DBL_EPSILON * true real value.  (DBL_EPSILON = 2^-52, which is approx. 2.22e-16)

"This means, the larger your numbers, the larger the absolute error will be."

So, for comparing double numbers like forex prices around 1.0, use a small epsilon like 1e-12. To handle comparison of larger numbers like volumes (tens or hundreds), you can use a larger epsilon like 1e-10 or 1e-8 to be on the safe side. These numbers represents the maximum expected calculation (round-off) errors that can be encountered based on the magnitude of the numbers.

This is an inherent feature (or bug!) in floating-point numbers as it works in binary bits 0 and 1, not in decimals 0 to 9 like humans. This is called the round-off error after performing math operations.


For example, the fp result of 0.1 + 0.2 may differ from the true real result 0.3 by a very tiny amount.

This can be explained as:

Although the literal 0.3 is represented exactly as double, 0.1+0.2 is not exactly equal to 0.3, because a round-off error was introduced (its magnitude can be calculated as discussed above) during the math calculation.

So, any difference that is larger than those tiny calculation errors is considered a true difference, rather than a calculation (round off) error. For example if you compare your calculated SL (0.1+0.2) to the stoploss price (0.3) on the server (in order to move your trailing stop), do not use  == != >= <= > < because there may be a tiny error in your calculation, which you should omit or handle when comparing doubles. (for example, use the comparison macros in post #6)

This is also another method to check for equality, which scales the epsilon (max. roundoff) to the magnitude of the numbers, dynamically:


Edited:

For better handling of roundoffs after a series of math calculations, we can use a less tight epsilon

Thank you that's what i was looking for . 

 
amrali #: Thanks William for the link, but I did not find there any method of choosing the "optimal" epsilon for comparing doubles.

There is none; it matters what you are comparing. If you are comparing prices use ½ tick size, lots, ½ lot step.

1.234565000 is the same price as 1.23457499999 1.23457 ± 0.000005

 
William Roeder #:

There is none; it matters what you are comparing. If you are comparing prices use ½ tick size, lots, ½ lot step.

1.234565000 is the same price as 1.23457499999 1.23457 ± 0.000005

Thanks for the clarification🙏 I explained it already in #13.  
Reason: