Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 146

 
fxsaber:

Sie war vom ersten Beitrag an geschlossen. Wenn die Mindestzahl mit etwas weniger als eins multipliziert wird, erhält man Null.

Wie würde der korrekte Code aussehen?

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

Wie sieht der richtige Code aus?

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

Kompilierung: Ausdruck nicht boolesch

Ergebnis: inf



keine gute Option für mich

 
Hier gibt es kein Problem
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);
}


Ich tue es nicht selbst.


Für Ästheten können Sie eine DOUBLE-Struktur mit entsprechenden Operatoren erstellen. Mit der Praxis hat das aber wenig zu tun. In dem ursprünglichen praktischen Beispiel.

ForUM zum Thema Handel, automatisierte Handelssysteme und Strategietests

Merkmale der Sprache mql5, Feinheiten und Techniken

fxsaber, 2019.10.28 07:24

So verstrickt man sich in die Division durch Null, selbst mit einem Scheck.
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    
}


Der Fehler ist in der Tat verständlich. Aber beim Schreiben von Code wie diesem ist es nicht immer offensichtlich, dass eine solche Prüfung nicht ausreicht, um eine Division durch Null zu vermeiden.


Sie müssen lediglich das zu erstellende Array-Element auf Null setzen. Die fehlende Initialisierung ist in diesem Fall die Ursache für die Kollisionen. Deshalb habe ich in meinem Code einfach eine Nullstellung vorgenommen. Ich möchte mich nicht mit der allgemeinen Ansicht befassen.

 
Igor Makanu:

Kompilierung: Ausdruck nicht boolesch

Ergebnis: inf



keine gute Option für mich

Mit Ihnen stimmt etwas nicht.

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

Es ist eher verwirrend, warum die Division durch Null zu einer fpu-Ausnahme führt, zumindest bei mir.

 
Vict:

Irgendetwas führt Sie in die falsche Richtung.

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

fxsaber:
Kein Problem hier

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:

Prüfung auf Informationen

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


d.h. wie erwartet ist inf nicht NaN
 
fxsaber:
Hier gibt es kein Problem.
bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN);
}

Googelt man nach "C++ double zero divide", funktioniert euer Code nicht für nicht-normalisierte Zahlen, ihr braucht dies:

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


Meditationsschrift ))))

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

Interessantes Thema. Hier habe ich etwas gefunden. Besonders hervorzuheben ist der Theorieblock.

 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)

Auf diese Weise können alle Unterlauf- und Überlaufbedingungen sicher geschützt werden. Die obige Methode funktioniert jedoch nicht, wenn v oder u gleich Null ist. In solchen Fällen besteht die Lösung darin, auf einen anderen Algorithmus zurückzugreifen, z. B.(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     
}

Wozu? Alles, was ich sehe, ist eine idiotische Warnung, auch wenn sie absolut berechtigt ist.

Boolesche Konvertierungen

Ein prvalue vom Typ Integral, Gleitkomma, unscoped enumeration, pointer und pointer-to-member kann in einen prvalue vom Typ bool konvertiert werden.

Der Wert Null (für Integral-, Fließkomma- und nicht skopierte Aufzählungen) sowie der Null-Zeiger und die Null-Zeiger-auf-Member-Werte werden falsch. Alle anderen Werte werden wahr.

Im Allgemeinen ist es reine Ignoranz, diese IsEqual(), IsInf() und IsZerro() zu schreiben. Ich werde mich nicht an der Diskussion beteiligen.

 
Vict:

Wozu? Alles, was ich sehe, ist eine idiotische Warnung, die durchaus berechtigt ist.

Im Allgemeinen ist es völlig unwichtig, solche IsEqual(), IsInf(), IsZerro() zu schreiben. Ich werde mich nicht an der Diskussion beteiligen.

IsInf() und IsNaN() funktionieren,

IsEqual() und IsZerro() sind fragwürdig, von einigen Quellen als "Trick für Double" gegoogelt.