Features of the mql5 language, subtleties and tricks - page 301

 
Putnik #:
That's what the computer teacher at school said

to fire.

firstly, it is not faster, secondly, it is not more obvious to the reader, finally it is up to the compiler to make such micro-optimisations.

Well, and to boot, the "subtraction" operation is not allowed (makes sense) for all domains and classes. By replacing the == operator with a-b==0 you can make a programme invalid

 
Alexey Viktorov #:

Because direct comparison of real numbers often leads to wrong results. And because of this, some people thoughtlessly apply this method wherever necessary and wherever not necessary.

And in fact, the original variant, if it differs, is very insignificant.

Please, no discussion. But I certainly do not agree to this statement.

a-b==0 is as precise as a==b. This is true for all data types, also for doubles. Else the CPU would not be deterministic any more.

Floating points do have representation roundoffs, agreed, but no matter what value you put in, the same input will always produce the same output.

What you are achieving using a-b==0 is a fuzzyness around a very large value subtracting a very small value, you begin to "snap" your result to the upper or lower boundary of representation.

That is buggy code. Its not good, and will be very hard to debug.
 
Dominik Egert #:
No discussion, please. But I certainly don't agree with that statement.

A-b==0 is just as accurate as a==b. This is true for all data types, including pairwise data. Otherwise, the processor would cease to be deterministic.

Floating points have rounding representations, I agree, but no matter what value you input, the same input will always give the same output.

What you achieve by using a-b==0 is fuzziness around a very large value when subtracting a very small value, you start to "tie" your result to the upper or lower bound of the representation.

This is glitchy code. It's not good, and it's going to be very difficult to debug.

Comparison

if(iOpen(NULL, 0, 0) == iClose(NULL, 0, 0)) // doesn't always work
if(iOpen(NULL, 0, 0) - iClose(NULL, 0, 0) == 0) // always works

I don't know which is faster, but we also need reliability of conditions

 
Dominik Egert #a-b==0 is as precise as a==b. This is true for all data types, also for doubles.
double a = 0.1 + 0.2;
double b = 0.3;

Print("a = ", a);
Print("b = ", b);

a = 0.30000000000000004

b = 0.3

That’s exactly why a - b == 0 is not safe for doubles.

Why a != b? Because neither 0.1, nor 0.2, nor 0.3 can be represented exactly in binary with the double type (64-bit IEEE 754).

 
Vitaly Muzichenko #:

Comparison

I don't know which is faster, but we also need reliability of conditions

In this particular example, this is even more reliable:

if(MathAbs(iOpen(NULL, 0, 0) - iClose(NULL, 0, 0)) <_Point)

In fact, in all other double numbers.

 
Also normalise the difference to a point, and it's great.)
 

If two double numbers are really equal in value, then the comparison "==" will be true, and the comparison a == b makes sense absolutely and is equal to the comparison a - b == 0.0.

So you just have to realise that writing a value in number code is not always equivalent to the very value of the number that the variable stores. I have never had any problems with direct comparison of two double numbers.

Another thing is that when we want to make a comparison with a specified precision, rather than a comparison of variable values (for example, two quotes), it is useful to compare the difference with tickSize rather than with point.

The code demonstrating the above:

input double      Input1 = 0.1;
input double      Input2 = 0.2;
input double      Input3 = 0.3;

void OnStart()
{
  double a = Input1 + Input2;
  double b = Input3;

  Print ("a = ", a);                              //a = 0.30000000000000004
  Print ("b = ", b);                              //b = 0.3
  Print (a == b);                                 //false
  Print (a - b);                                  //5.551115123125783e-17
  Print (Input1 + Input2 == Input3);              //false
  Print (Input1 + Input2 - Input3 < DBL_EPSILON); //true
  Print (DBL_EPSILON);                            //2.220446049250313e-16
  
  double d1 = DBL_MAX;              
  double d2 = DBL_MAX;              
  Print (d1 == d2);                               //true
  Print (d1 - d2 == 0.0);                         //true
  Print (d1 - d2 < DBL_EPSILON);                  //true
}
 
Andrey Dik #:

If two double numbers are really equal in value, then the comparison "==" will be true, and the comparison a == b makes sense absolutely and is equal to the comparison a - b == 0.0.

So you just have to realise that writing a value in number code is not always equivalent to the very value of the number that the variable stores. I have never had any problems with direct comparison of two double numbers.

Another thing is that when we want to make a comparison with a specified precision, rather than a comparison of variable values (for example, two quotes), it is useful to compare the difference with tickSize rather than with point.

The code demonstrating the above:

It is true that a == b works if both values are exactly the same in memory, as in your examples with constants.

But in practice, most doubles come from operations that introduce rounding errors, and that's where == (and also a - b == 0.0) become unreliable.

That's why it is recommended to use MathAbs(a - b) < ε, where ε depends on the context ( _Point, tick size or DBL_EPSILON).

double a = 1.0000001 - 0.0000001;
double b = 1.0;
Print(a == b);                       // false
Print(MathAbs(a - b) < DBL_EPSILON); // true
 
Miguel Angel Vico Alba DBL_EPSILON).

Here, it is because of the highlighted that I wrote the post above. Recommended by whom? - For what cases is it recommended?

We want to compare variables by their value - we use their direct comparison. We want to compare with a given precision - we compare the difference of numbers with a given precision. There is no sorcery here, you can and should use both, it depends on the specific task.

 
Andrey Dik #:

Here, it is because of the highlighted that I wrote the post above. Recommended by whom? - For what cases is it recommended?

We want to compare variables by their value - we use their direct comparison. We want to compare with a given precision - we compare the difference of numbers with a given precision. There is no sorcery here, you can and should use both, it depends on the specific task.

I totally agree, Andrey. It's not a matter of one form being "good" and the other "bad", but of understanding when to use each one.

The use of == is perfectly valid if we know that the values are exact (e.g. constants or controlled data). The use of MathAbs(a - b) < ε simply adds a useful tolerance when there are previous operations that may introduce small inaccuracies, as often happens in intermediate calculations with double.

In the end, as you say, it depends on the specific case and the level of precision we need.