¿Puede el precio != el precio ? - página 7

 

WHRoeder: ¿este código es bueno (especialmente comprobar "añadido" y "por defecto")? También puede servir como una fácil referencia final para aquellos que visitan este hilo y sólo ir la última página (como lo hice)

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

Ese código no es preciso.

¿Cómo se puede utilizar if( !MathAbs( a - b ) > Punto/2) para comparar la igualdad? Eso te diría que 1.4999 == 1.5000

 
SDC: ¿Cómo se puede utilizar if( !MathAbs( a - b ) > Point/2) para comparar la igualdad? Eso te diría que 1.4999 == 1.5000
  1. No es así
    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. Y yo le había señalado a Roel13 en un MP que el GEQ/LEQ debe ser -Punto/2 pero no editó el post
  3. Y como ya publiqué anteriormente, sólo hay que preocuparse por esas tonterías si la igualdad/no igualdad es importante. Si quieres abrir por encima del máximo de una vela, ¿importa si (debido al redondeo) que pueda dispararse exactamente en el máximo? Si no es así, simplemente use bid > high[].
 

Utilizo

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


o para los dobles que no son precios reales, una mayor precisión

if(NormalizeDouble(value1-value2,8)==0)
 
SDC: Yo uso
if(NormalizeDouble(price1-price2,Digits)==0)
Lee el primer post y sabrás por qué no es una buena idea.
 

El post de Raptors sobre este código

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

Así que si usted utiliza,

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

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

He probado ese método de varias maneras y no he encontrado un escenario en el que no devuelva el resultado esperado o deseado.
 

Código final... Gracias 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);
}


Y, tal vez una función secundaria para comparar todos los otros dobles que no son los precios ...

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


Ver también 'MQL4 Reference > Language Basics > Data Types > Real Types (double, float)' en lo que respecta al uso de números pequeños para la comparación.

Tal vez alguien sabe cómo escribir 0,00...1 mejor en exponer

 
Roel13: Quizá alguien sepa cómo escribir mejor 0,00...1 en expon
// case LT: return(b-a>0.0000000000000000000000000000001);
// case LT: return(b-a>1.0e-30);
Ver Tipos Reales (double, float) - Documentación MQL4
Obsérvese que el valor de épsilon en el ejemplo anterior no puede ser inferior a la constante predefinida DBL_EPSILON. El valor de esta constante es 2,2204460492503131e-016.
Una vez más, nada de esto es necesario, excepto en el caso en que el igual / no igual es importante. Por ejemplo, abrir por encima de la alta anterior, usted no quiere abrir en la alta debido al redondeo.
 

Así que hay algo más interesante que he encontrado, potencialmente en relación con "// 0 comparar no necesita esta función".

Tal vez sea un error sólo en las últimas versiones, no estoy seguro. Comparar con 0 ya no funciona correctamente. Tuve que recurrir a algo poco amigable como

resultado=(int(resultado*100)/100.0); // Resolución 2 dígitos

Sólo para asegurarme de que los valores 0 terminaban realmente como valores 0.

WHRoeder, gracias. Hay que estudiar más :)

 

Creo que este tema se trata con demasiada complejidad innecesaria.

Intenta hacer la vida de tu programador siempre lo más fácil posible. Escriba definiciones (o siga con métodos si realmente debe hacerlo) en aquellas clases donde necesite sus comparaciones dobles:

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

Cuando necesites comparar dos dobles entonces úsalo en una condición como esta:

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

Si quieres ver si un doble es cero (o muy, muy cercano a cero) usa una condición como esta:

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


Como nota al margen, ya que veo muchos posts hablando de divisiones:

Con la encapsulación tendemos a olvidarnos de los costes del código que se "externaliza" a algunos métodos de utilidad. Recuerde que las divisionesson computacionalmente muy costosas! Especialmente, una vez envuelto en métodos de utilidad agradable en algún lugar en las clases de utilidad, empezamos a usarlos en todas partes en los indicadores o EAs y han olvidado por mucho tiempo lo que los pasos computacionales que realizan. Cuando usamos el probador de estrategias pagamos mucho tiempo innecesario por nuestra dejadez.

Regla de oro: Las sumas y restas son mucho más rápidas que las multiplicaciones y divisiones. La operación de división es la que más tiempo de cálculo requiere.Optimice las divisiones, siempre que sea posible. Si el denominador es fijo como en este bucle...

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

entonces sustituye el denominador x por su valor invertido 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.
    // ...
}

Además, si el resultado de una división es siempre el mismo, entonces haz el cálculo una vez y guarda el resultado en una variable para que puedas usarlo en cualquier parte de tu código (por ejemplo, en los bucles):

double tradesPerDay = totalTradesPerYear/365;

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

Saludos,

A.T.