Caractéristiques du langage mql5, subtilités et techniques - page 146

 
fxsaber:

Il a été fermé dès le premier message. Lorsque le nombre minimum est multiplié par un nombre inférieur à un, on obtient zéro.

à quoi ressemblerait le code correct ?

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

À quoi ressemblera le bon code ?

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

compilation : expression non booléenne

résultat : inf



ce n'est pas une bonne option pour moi

 
Il n'y a pas de problème ici.
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);
}


Je ne le fais pas moi-même.


Pour les esthètes, vous pouvez créer une structure DOUBLE avec les opérateurs appropriés. Mais cela n'a pas grand-chose à voir avec la pratique. Dans l'exemple pratique original.

ForUM sur le trading, les systèmes de trading automatisés et les tests de stratégie

Caractéristiques du langage mql5, subtilités et techniques

fxsaber, 2019.10.28 07:24

C'est une façon de se laisser entraîner dans la division par zéro, même avec un chèque.
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    
}


L'erreur est en fait compréhensible. Mais en écrivant du code comme celui-ci, il n'est pas toujours évident qu'une telle vérification n'est pas suffisante pour éviter la division par zéro.


Il suffit de mettre à zéro l'élément du tableau en cours de création. C'est l'absence d'initialisation qui provoque les collisions dans ce cas. C'est pourquoi j'ai simplement fait une mise à zéro dans mon code. Je ne veux pas m'embêter avec l'opinion générale.

 
Igor Makanu:

compilation : expression non booléenne

résultat : inf



ce n'est pas une bonne option pour moi

Il y a quelque chose qui ne va pas chez vous.

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

La raison pour laquelle la division par zéro provoque une exception de l'unité centrale de traitement est plus confuse, du moins pour moi.

 
Vict:

Quelque chose te fait prendre le mauvais chemin.

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

fxsaber:
Aucun problème ici

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 --> vrai

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

UPD :

vérifier l'existence de l'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


i.e. comme prévu inf ce n'est pas NaN
 
fxsaber:
Il n'y a pas de problème.
bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN);
}

En cherchant sur Google "C++ double zero divide", votre code ne fonctionnera pas pour les nombres non normalisés, vous avez besoin de ceci :

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


script de méditation ))))

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

Sujet intéressant. J'ai trouvé quelque chose ici. Particulièrement remarquable dans le bloc théorique.

 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)

De cette façon, toutes les conditions d'underflow et d'overflow peuvent être protégées en toute sécurité. Cependant, la méthode ci-dessus ne fonctionne pas lorsque v ou u est égal à zéro. Dans ce cas, la solution consiste à recourir à un algorithme différent, par exemple(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 quoi ? Tout ce que je vois, c'est un avertissement idiot, même s'il est tout à fait valable.

Conversions booléennes

Une valeur de prvalue de type intégral, à virgule flottante, d'énumération non chiffrée, de pointeur et de pointeur à membre peut être convertie en une valeur de prvalue de type bool.

La valeur zéro (pour les énumérations intégrales, à virgule flottante et non chiffrées), le pointeur nul et les valeurs du pointeur nul vers le membre deviennent faux. Toutes les autres valeurs deviennent vraies.

En général, c'est de la pure ignorance que d'écrire ces IsEqual(), IsInf() et IsZerro(). Je n'entrerai pas dans la discussion.

 
Vict:

A quoi ? Tout ce que je vois, c'est un avertissement stupide, qui est parfaitement valable.

En général, c'est une ignorance totale d'écrire de telles IsEqual(), IsInf(), IsZerro(). Je n'entrerai pas dans la discussion.

IsInf() et IsNaN() fonctionnent,

IsEqual() et IsZerro() sont discutables, ils ont été googlés à partir de certaines sources comme "truc pour le double".

Raison: