Características da linguagem mql5, subtilezas e técnicas - página 146

 
fxsaber:

Foi encerrado logo a partir do primeiro posto. Quando o número mínimo é multiplicado por algo menos do que um, obtém-se zero.

como seria o código correcto?

// Неправильно написанная функция.
double WrongFunc( const double Num )
{
  return(Num ? 1 / (0.1 * Num) : 0);
}
 
Igor Makanu:

Como será o código certo?

 
fxsaber:
void OnStart()
{
  double d = DBL_MIN - DBL_MIN/10.0;
  Print(WrongFunc(d));
}
//_______________________________________________________________________
double WrongFunc( const double Num )
{
  return(0.1 * Num ? 1 / (0.1 * Num) : 0);
}

compilação: expressão não booleana

resultado: inf



não é uma boa opção para mim

 
Não há aqui nenhum problema
bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN);
}

double WrongFunc( const double Num )
{
  return(!IsNull(0.1 * Num) ? 1 / (0.1 * Num) : 0);
}


Não sou eu que o faço.


Para estetas, pode criar uma estrutura DOUBLE com operadores apropriados. Mas isto tem pouco a ver com a prática. No exemplo prático original.

ForUM sobre comércio, sistemas automatizados de comércio e testes estratégicos

Características da linguagem mql5, complexidades e técnicas

fxsaber, 2019.10.28 07:24

Maneira de ser apanhado na divisão por zero, mesmo com um cheque.
void OnStart()
{  
  const double Profit = 100;
  const double Lots = 1;

  double TickValue[];  
  ArrayResize(TickValue, 1);
  
  const double Points = TickValue[0] ? Profit / (Lots * TickValue[0] * _Point) : 0; // zero divide    
}


O erro é, de facto, compreensível. Mas enquanto se escreve um código como este, nem sempre é óbvio que tal verificação não é suficiente para evitar a divisão por zero.


Só precisa de zerar o item da matriz que está a ser criado. É a ausência de inicialização que causa colisões neste caso. É por isso que simplesmente fiz a zeragem no meu código. Não quero incomodar-me com a visão geral.

 
Igor Makanu:

compilação: expressão não booleana

resultado: inf



não é uma boa opção para mim

Há algo de errado consigo.

#define  DBL_MIN_DENORM  4.94066 e-324
   Print(DBL_MAX*1.1); // inf
   Print(DBL_MIN_DENORM*0.5); // 0

É mais confuso porque dividir por zero dá uma excepção, pelo menos para mim.

 
Vict:

Alguma coisa está a levar-vos a todos ao caminho errado.

void OnStart()
{
  double Num=0.0;
  if(0.1 * Num){} // expression not boolean     
}

fxsaber:
Aqui não há problema

bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN);
}

void OnStart()
{
  union ULongTODouble {
      ulong ul;
      double d;
   } ULongDouble;

   ulong nan = 18446744073708624091;
   ULongDouble.ul = nan;
   double tst = DBL_MIN - DBL_MIN/10000.0;
   Print(tst," --> ",IsNull(tst));
   tst = ULongDouble.d;
   Print(tst," --> ",IsNull(tst));
}
//_______________________________________________________________________

bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN || Num!=Num);
}

2019.10.28 20:45:47.010 tst1 (EURUSD,H4) 2.224851351121351e-308 --> true

2019.10.28 20:45:47.010 tst1 (EURUSD,H4) -nan --> true

UPD:

verificar por inf

void OnStart()
{
   double dev = 1.0 / 4.940656458412465 e-324;
   Print("1. dev = ", dev, " ---> ", dev != dev);
   Print("2. dev = ", dev, " ---> ", IsInf(dev));
   dev = 1.0 / dev;

}
//+------------------------------------------------------------------+
bool IsInf(const double Num)
{
   return (Num > DBL_MAX || Num < DBL_MIN);
}
//+------------------------------------------------------------------+

2019.10.28 22:04:00.163 tst1 (EURUSD,H4) 1. dev = inf ---> false

2019.10.28 22:04:00.163 tst1 (EURUSD,H4) 2. dev = inf ---> true


isto é, como esperado, não é NaN
 
fxsaber:
Não há aqui qualquer problema.
bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN);
}

Pesquisado no Google "C++ dupla divisão zero", o seu código não funcionará para números não normalizados, precisa disto:

bool IsZerro(const double value)
{
   return(fabs(value) * DBL_EPSILON == 0.0);
}


guião de meditação ))))

void OnStart()
{
   union ULongTODouble {
      ulong ulong_;
      double double_;
   } ULongDouble;
   ulong i = 0;
   ulong count_NaN = 0;
   ulong count_Zerro = 0;
   double last_double = 0.0;
   while(i < ULONG_MAX) {
      ULongDouble.ulong_ = i;
      double double_result = ULongDouble.double_;
      if(IsNaN(double_result)) count_NaN++;
      else {
         if(IsZerro(double_result)) {
            count_Zerro++;
            last_double = double_result;
         }
      }
      if(i % 1000000000 == 0) Print("i = ", i, " , NaN = ", count_NaN, " , Zerro = ", count_Zerro, " , last_double = ", last_double);
      i++;
   }
   Print("NaN = ", count_NaN);
   Print("Zerro = ", count_Zerro);
}
//+------------------------------------------------------------------+
bool IsZerro(const double value)
{
   return(fabs(value) * DBL_EPSILON == 0.0);
}
//+------------------------------------------------------------------+
bool IsNaN(const double value)
{
   return(value != value);
}
//+------------------------------------------------------------------+
bool IsInf(const double value)
{
   return (value > DBL_MAX || value < DBL_MIN);
}
//+------------------------------------------------------------------+
bool IsEqual(const double value1, const double value2)
{
   return(fabs(value1 - value2) <= DBL_EPSILON);
}
//+------------------------------------------------------------------+
 

Tema interessante. Encontrei algo aqui. Particularmente digno de nota no bloco teórico.

 abs(u - v)/abs(u) <= epsilon
&& abs(u - v)/abs(v) <= epsilon; // (4)
   abs(u - v)/abs(u) <= epsilon
|| abs(u - v)/abs(v) <= epsilon; // (5)

Desta forma, todas as condições de sub e sobrefluxo podem ser guardadas em segurança. O acima referido, porém, não funcionará quando v ou u for zero. Nestes casos, a solução é recorrer a um algoritmo diferente, por exemplo(1).

Floating point comparison - 1.71.0
  • www.boost.org
Unless specified otherwise, when a value of floating-point type is compared inside a assertion, operators , , etc. defined for this type are used. However for floating point type, in most cases what is needed is not an equality (or inequality), but a verification that two numbers are or . For that purpose, a parameter that will instruct the...
 
Igor Makanu:
void OnStart()
{
  double Num=0.0;
  if(0.1 * Num){} // expression not boolean     
}

A quê? Tudo o que vejo é um aviso idiota, se for absolutamente válido.

Conversões booleanas

Um prvalue dos tipos integral, ponto flutuante, enumeração não copiada, ponteiro, e ponteiro para membros pode ser convertido em um prvalue do tipo bool.

O valor zero (para enumeração integral, ponto flutuante e não copiado) e o ponteiro nulo e os valores nulos de ponteiro para membro tornam-se falsos. Todos os outros valores tornam-se verdadeiros.

Em geral, é pura ignorância escrever estes IsEqual(), IsInf() e IsZerro(). Não vou entrar na discussão.

 
Vict:

A quê? Tudo o que vejo é um aviso idiota, se for absolutamente válido.

Em geral, é completa ignorância escrever tais IsEqual(), IsInf(), IsZerro(). Não vou entrar na discussão.

IsInf() e IsNaN() estão a funcionar,

IsEqual() e IsZerro() são questionáveis, pesquisadas no Google a partir de algumas fontes como "truque para o dobro".

Razão: