Kann Preis != Preis ? - Seite 7

 

WHRoeder: dieser Code gut (vor allem überprüfen "hinzugefügt" und "Standard")? Es kann auch als eine einfache letzte Referenz für diejenigen dienen, die diesen Thread besuchen und nur die letzte Seite gehen (wie ich es tat)

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

Dieser Code ist nicht genau.

Wie kann if( !MathAbs( a - b ) > Point/2) zum Vergleich auf Gleichheit verwendet werden? Das würde Ihnen sagen, dass 1.4999 == 1.5000

 
SDC: Wie kann if( !MathAbs( a - b ) > Point/2) zum Vergleich auf Gleichheit verwendet werden? Das würde Ihnen sagen, dass 1,4999 == 1,5000
  1. Das ist nicht der Fall.
    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. Und ich hatte Roel13 in einer PM darauf hingewiesen, dass der GEQ/LEQ -Point/2 sein muss, aber er hat den Beitrag nicht bearbeitet
  3. Und wie ich schon früher gepostet habe, muss man sich um solchen Unsinn nur kümmern, wenn die Gleichheit/Nicht-Gleichheit wichtig ist. Wenn Sie oberhalb des Hochs einer Kerze eröffnen wollen, spielt es dann eine Rolle, ob es (wegen der Rundung) genau auf dem Hoch auslösen könnte? Wenn nein, verwenden Sie einfach bid > high[].
 

Ich verwende

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


oder für Doppelwerte, die keine tatsächlichen Preise sind, eine höhere Genauigkeit

if(NormalizeDouble(value1-value2,8)==0)
 
SDC: Ich benutze
if(NormalizeDouble(price1-price2,Digits)==0)
Lesen Sie den allerersten Beitrag und Sie werden erfahren, warum das keine gute Idee ist.
 

Raptors Beitrag über diesen Code

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

Wenn Sie also verwenden,

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

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

Ich habe diese Methode auf verschiedene Arten getestet und habe kein Szenario gefunden, in dem sie nicht das erwartete oder gewünschte Ergebnis liefert.
 

Endgültiger Code... Danke 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);
}


Und, vielleicht eine sekundäre Funktion für den Vergleich aller anderen Doubles, die keine Preise sind...

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


Siehe auch 'MQL4 Referenz > Grundlagen der Sprache > Datentypen > Reelle Typen (double, float)' in Bezug auf die Verwendung kleiner Zahlen für den Vergleich.

Vielleicht weiß jemand, wie man 0.00...1 besser in expon schreiben kann.

 
Roel13: Vielleicht weiß jemand, wie man 0.00...1 besser in expon schreiben kann.
// case LT: return(b-a>0.0000000000000000000000000000001);
// case LT: return(b-a>1.0e-30);
Siehe Reelle Typen (double, float) - MQL4 Dokumentation
Beachten Sie, dass der Wert von epsilon im obigen Beispiel nicht kleiner sein kann als die vordefinierte Konstante DBL_EPSILON. Der Wert dieser Konstante ist 2.2204460492503131e-016.
Auch dies ist nicht notwendig, außer in dem Fall, wo die gleich/nicht gleich wichtig ist. Wenn Sie z.B. über dem vorherigen Hoch eröffnen, wollen Sie nicht am Hoch eröffnen, um abzurunden.
 

Es gibt also noch etwas Interessantes, das ich gefunden habe, möglicherweise im Zusammenhang mit "// 0 compare doesn't need this function".

Vielleicht ein Fehler nur in den neuesten Versionen, nicht sicher. Der Vergleich mit 0 funktioniert nicht mehr richtig. Ich musste auf etwas Unfreundliches zurückgreifen wie;

Ergebnis=(int(Ergebnis*100)/100.0); // Auflösung 2 Ziffern

Nur um sicherzustellen, dass 0-Werte tatsächlich als 0-Werte enden.

WHRoeder, danke. Mehr Studium nötig :)

 

Ich denke, dieses Thema wird mit zu viel unnötiger Komplexität behandelt.

Versuchen Sie, Ihren Programmierern das Leben immer so einfach wie möglich zu machen. Schreiben Sie Defines (oder gehen Sie mit Methoden voran, wenn Sie wirklich müssen) in den Klassen, in denen Sie Ihre Doppelvergleiche benötigen:

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

Wenn Sie zwei Doubles vergleichen müssen, verwenden Sie sie in einer Bedingung wie dieser:

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

Wenn Sie wissen wollen, ob ein Double Null ist (oder sehr, sehr nahe an Null), verwenden Sie eine Bedingung wie diese:

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


Nebenbei bemerkt, da ich viele Beiträge sehe, die über Divisionen sprechen:

Bei der Kapselung neigen wir dazu, die Kosten des Codes zu vergessen, der in einige Utility-Methoden "ausgelagert" wird. Erinnern Sie sich daran, dass Divisionenrechnerisch sehr teuer sind! Vor allem, wenn sie einmal in netten Utility-Methoden irgendwo in Utility-Klassen verpackt sind, fangen wir an, sie überall in Indikatoren oder EAs zu verwenden und haben längst vergessen, welche Rechenschritte sie ausführen. Bei der Verwendung des Strategietesters zahlen wir für unsere Schlampigkeit eine Menge unnötiger Zeit.

Faustformel: Additionen und Subtraktionen sind viel, viel schneller als Multiplikationen und Divisionen. Die Division benötigt die meiste Rechenzeit.Optimieren Sie Divisionen- wo immer möglich! Wenn der Nenner wie in dieser Schleife fest ist...

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

dann ersetzen Sie den Nenner x durch seinen invertierten Wert 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.
    // ...
}

Wenn das Ergebnis einer Division immer gleich ist, dann führen Sie die Berechnung einmal durch und speichern Sie das Ergebnis in einer Variablen, damit Sie es überall in Ihrem Code verwenden können (z. B. in Schleifen):

double tradesPerDay = totalTradesPerYear/365;

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

Prost!

A.T.