Can price != price ? - page 7

 

WHRoeder : ce code est bon (surtout vérifier "ajouté" et "par défaut") ? Il peut également servir de référence finale facile pour ceux qui visitent ce fil et vont juste à la dernière page (comme je l'ai fait).

#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
  }
}
 

Ce code n'est pas exact.

Comment peut-on utiliser if( !MathAbs( a - b ) > Point/2) pour comparer l'égalité ? Cela vous dirait que 1.4999 == 1.5000

 
SDC: Comment peut-on utiliser if( !MathAbs( a - b ) > Point/2) pour comparer l'égalité ? Cela vous dirait que 1.4999 == 1.5000
  1. Ce n'est pas le cas
    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. Et j'ai fait remarquer à Roel13 dans un MP que le GEQ/LEQ doit être -Point/2 mais il n'a pas modifié le message.
  3. Et comme je l'ai déjà dit, vous ne devez vous préoccuper de ces absurdités que si l'égalité ou la non-égalité est importante. Si vous voulez ouvrir au-dessus du plus haut d'une bougie, est-ce important si (à cause des arrondis) cela peut se déclencher exactement au plus haut ? Si non, utilisez simplement bid > high[].
 

J'utilise

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


ou pour les doubles qui ne sont pas des prix réels, une plus grande précision

if(NormalizeDouble(value1-value2,8)==0)
 
SDC: J'utilise
if(NormalizeDouble(price1-price2,Digits)==0)
Lisez le tout premier message et vous apprendrez pourquoi ce n'est pas une bonne idée.
 

Raptors post à propos de ce code

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

Donc si vous utilisez ,

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

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

J'ai testé cette méthode de diverses manières et je n'ai pas trouvé de scénario où elle ne renverrait pas le résultat attendu ou souhaité.
 

Code final... Merci 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);
}


Et, peut-être une fonction secondaire pour comparer tous les autres doubles qui ne sont pas des prix...

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);
}


Voir aussi 'MQL4 Reference > Language Basics > Data Types > Real Types (double, float)' en ce qui concerne l'utilisation de petits nombres pour la comparaison.

Peut-être que quelqu'un sait comment mieux écrire 0.00...1 en exponentiel.

 
Roel13: Peut-être que quelqu'un sait comment mieux écrire 0,00...1 en exponentiel.
// case LT: return(b-a>0.0000000000000000000000000000001);
// case LT: return(b-a>1.0e-30);
Voir Types réels (double, float) - Documentation MQL4
Notez que la valeur d'epsilon dans l'exemple ci-dessus ne peut pas être inférieure à la constante prédéfinie DBL_EPSILON. La valeur de cette constante est 2.2204460492503131e-016.
Encore une fois, rien de tout cela n'est nécessaire, sauf dans le cas où les égaux/non égaux sont importants. Par exemple, ouvrir au-dessus du sommet précédent, vous ne voulez pas ouvrir au sommet à cause de l'arrondi.
 

Il y a donc quelque chose d'autre d'intéressant que j'ai trouvé, potentiellement en relation avec "// 0 compare n'a pas besoin de cette fonction".

Peut-être un bug uniquement dans les dernières versions, pas sûr. La comparaison avec 0 ne fonctionne plus correctement. J'ai dû recourir à quelque chose de peu convivial comme ;

outcome=(int(outcome*100)/100.0) ; // Résolution 2 chiffres

Juste pour s'assurer que les valeurs 0 finissent effectivement par être des valeurs 0.

WHRoeder, merci. Une étude plus approfondie est nécessaire :)

 

Je pense que ce sujet est traité avec trop de complexité inutile.

Essayez de rendre la vie de votre programmeur toujours aussi facile que possible. Ecrivez des définitions (ou allez-y avec des méthodes si vous le devez vraiment) dans les classes où vous avez besoin de vos comparaisons de doubles :

// 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)

Lorsque vous avez besoin de comparer deux doubles, utilisez-le dans une condition comme celle-ci :

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

Si vous voulez voir si un double est égal à zéro (ou très, très proche de zéro), utilisez une condition comme celle-ci :

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


En passant, puisque je vois beaucoup de messages parlant de divisions :

Avec l'encapsulation, nous avons tendance à oublier les coûts du code qui est "externalisé" vers certaines méthodes utilitaires. Rappelez-vous queles divisions sont très coûteuses en termes de calcul ! En particulier, une fois enveloppées dans de jolies méthodes utilitaires quelque part dans des classes utilitaires, nous commençons à les utiliser partout dans des indicateurs ou des EA et nous avons oublié depuis longtemps quelles étapes de calcul elles effectuent. Lorsque nous utilisons le testeur de stratégie, nous payons beaucoup de temps inutile pour notre négligence.

Règle de base: Les additions et les soustractions sont beaucoup plus rapides que les multiplications et les divisions. L'opération de division est celle qui prend le plus de temps de calcul.Optimisez les divisions- partout où c'est possible ! Si le dénominateur est fixe comme dans cette boucle...

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

alors remplacez le dénominateur x par sa valeur inversée 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.
    // ...
}

De même, si le résultat d'une division est toujours le même, effectuez le calcul une fois et enregistrez le résultat dans une variable afin de pouvoir l'utiliser partout dans votre code (par exemple dans les boucles) :

double tradesPerDay = totalTradesPerYear/365;

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

Merci,

A.T.