O preço da lata != preço ? - página 2

 

Se for para comparação, então você poderia facilmente criar sua própria função:

bool checkDoubles(double a, double b, string check)
{
if(check==">"){
if (a - b > Point / 2)return(1);else return (0);
}else if(check=="<"){
if (b - a > Point / 2)return(1);else return (0);
}else if(check==">="){
if (a - b > -Point)return(1);else return (0);
}if(check=="<="){
if (b - a > -Point)return(1);else return (0);
}else if(check=="!="){
if (MathAbs(a - b) > Point / 2)return(1);else return (0);
}else {
Print("Sorry you've entered a wrong check value");
}
return (0);
}

É apenas um pensamento.

 
heelflip43:

Se for para comparação, então você poderia facilmente criar sua própria função:

É apenas um pensamento.


É um bom pensamento, obrigado por isso :-)
 

O uso de "Ponto" ou "Ponto/2.0" não é um valor de diferença muito bom, IMO. O erro roundoff introduzido por NormalizeDouble (que hoje me queimei), certamente é muito menor que 8 dígitos, mais provavelmente 15 dígitos.

Tendo em vista as dicas anteriores, e tendo feito algumas mudanças e montado a seguinte rotina que parece funcionar bem (mesmo usando a "diff" até 15 casas decimais), embora ainda não tenha sido rigorosamente testada:

//+------------------------------------------------------------------+
bool AvsB(double A, string checkStr, double B)
{
   //checkStr = StringTrimLeft(StringTrimRight(checkStr));
   double diff = 0.000000000000001; // 15 decimal places
   //double diff = 0.000000005;
   //double diff = 0.00000001;
   if     (checkStr == ">" ){if (A - B >  diff)return(true);else return(false);}
   else if(checkStr == "<" ){if (B - A >  diff)return(true);else return(false);}
   else if(checkStr == ">="){if (A - B > -diff)return(true);else return(false);}
   else if(checkStr == "<="){if (B - A > -diff)return(true);else return(false);}
   else if(checkStr == "!="){if (MathAbs(A - B) >  diff)return(true);else return(false);}
   else if(checkStr == "=" || checkStr == "=="){if (MathAbs(A - B) <  diff)return(true);else return(false);}
   else {Print("Sorry, bad usage: AvsB(A, checkStr, B).  Wrong checkStr value: ",checkStr);}
   return(false);
} // end of AvsB
//+------------------------------------------------------------------+

Here is a check of the obvious:

   if (1.34929 == NormalizeDouble(1.34929 , 5))  Alert("MT4 Pass");
   else Alert("MT4 FAIL.  ROUNDOFF BUG");    // Yes, this is what MT4 does, a fail.

   if (AvsB(1.34929 ,"==", NormalizeDouble(1.34929 , 5)))  Alert("AvsB Pass");  // It does pass using the AvsB routine!
   else Alert("AvsB FAIL.  ROUNDOFF BUG"); 
 

Aqui está mais uma possível rotina que pode comparar, mas também pode normalizar internamente tanto A e/ou B, e também irá relaxar a diferença de comparação (de A-B ou B-A) para um número maior baseado em "dígitos". Duvido que esta rotina seja necessária em comparação com a simples "AvsB" acima, mas ela é oferecida para seu uso conforme desejado:

//+------------------------------------------------------------------+
bool AvsB_nA_nB_digits(double A, string checkStr, double B, bool normalizeA, bool normalizeB, int digits)
{
   //checkStr = StringTrimLeft(StringTrimRight(checkStr));
   if (normalizeA) A = NormalizeDouble(A,MathMin(8,digits));
   if (normalizeB) B = NormalizeDouble(B,MathMin(8,digits));
   
   double diff;
   switch(digits)
   {
      case 0  : diff = 0.5; break; // Or 1.0 ??
      case 1  : diff = 0.1; break;
      case 2  : diff = 0.01; break;
      case 3  : diff = 0.001; break;
      case 4  : diff = 0.0001; break;
      case 5  : diff = 0.00001; break;
      case 6  : diff = 0.000001; break;
      case 7  : diff = 0.0000001; break;
      case 8  : diff = 0.00000001; break;
      case 9  : diff = 0.000000001; break;
      case 10 : diff = 0.0000000001; break;
      case 11 : diff = 0.00000000001; break;
      case 12 : diff = 0.000000000001; break;
      case 13 : diff = 0.0000000000001; break;
      case 14 : diff = 0.00000000000001; break;
      default : diff = 0.000000000000001; break; // 15 decimal places max (I think)
   }
   
   if     (checkStr == ">" ){if (A - B >  diff)return(true);else return(false);}
   else if(checkStr == "<" ){if (B - A >  diff)return(true);else return(false);}
   else if(checkStr == ">="){if (A - B > -diff)return(true);else return(false);}
   else if(checkStr == "<="){if (B - A > -diff)return(true);else return(false);}
   else if(checkStr == "!="){if (MathAbs(A - B) >  diff)return(true);else return(false);}
   else if(checkStr == "=" || checkStr == "=="){if (MathAbs(A - B) <  diff)return(true);else return(false);}
   else {Print("Sorry, bad usage: AvsB(A, checkStr, B).  Wrong checkStr value: ",checkStr);}
   return(false);
} // end of AvsB_nA_nB_digits
//+------------------------------------------------------------------+
 
pips4life:

O uso de "Ponto" ou "Ponto/2.0" não é um valor de diferença muito bom, IMO. O erro roundoff introduzido por NormalizeDouble (que hoje me queimei), certamente é muito menor que 8 dígitos, mais provavelmente 15 dígitos.

Você quer o maior valor que não pode ser considerado erro roundoff ou equivalente, o menor valor que não pode ser considerado uma mudança de preço. Como os preços só podem mudar por um múltiplo de ponto, o ponto/2 é exatamente isso.

O valor duplo do corretor poderia ser de 1,234575000000000000 a 1,23458499999999999 e ainda ser considerado o mesmo preço de 1,23458.

Se você tivesse usado isto, não teria tido o problema:

if (a > b)
if (a - b > Point / 2.)
if (a >= b)
if (a - b > -Point/2.)
if (a != b)
if (MathAbs(a - b) > Point / 2.)
 

devemos evitar o uso de ??

ou talvez... eu tenho uma idéia de que podemos usara função MathRound

ex . duplo x= (MathRound( 1,37883 * 100000)) / 100000 ;

para que possamos fazer funcionar

double round ( double value )

{ int D= MathPow(10,Digits);

double x =  ( MathRound (value * D)) / D ;

return(x);

} 
 
*Põe sua gravata em posição com dois dedos* Só use normalizar o dobro nos cálculos que envolvem um valor duplo e não apenas em todos os lugares onde há um dobro.
 
tonny:
*Põe sua gravata em posição com dois dedos* Só use normalizar o dobro nos cálculos que envolvem um valor duplo e não apenas em todos os lugares onde há um dobro.
Ou simplesmente não use NormalizeDouble() de forma alguma, na maioria das vezes quando é usado não háabsolutamente nenhuma necessidade de usá-lo . . . erro 4107 pode ser resolvido usando NormalizeDouble(), mas há outras formas. Qualquer preço que venha de variáveis pré-definidas ou funções de série temporal nunca precisará ser Normalizado, nem o resultado de um número inteiro multiplicado por Ponto.
 
WDholic:

devemos evitar o uso de ??

ou talvez... eu tenho uma idéia de que podemos usar a função MathRound

ex . duplo x= (MathRound( 1,37883 * 100000)) / 100000 ;


Você ainda acaba com o dobro e ainda com a possibilidade de preço != preço

Cheguei a esta solução, que transforma as duplas em duplas, com o propósito de comparar as duplas. . .

int Flat(double ValueToFlatten)
   {
   double Power = MathPow(10, Digits);
   int ReturnValue;
   
   ReturnValue = MathRound(Power * (ValueToFlatten + (4.9/ (Power*10) ) ) ) ;
   return (ReturnValue);
   
   }

para que . . .

Flat(price) != Flat(price)

nunca será verdade.

 
Em muitos cálculos em vez da solução simples