Frage an die MQL4-Meister. Nochmals zu Double Compare. - Seite 6

 
VBAG:
...
Das Schöne an Irtrons Code ist seine Kompaktheit (absolut nichts extra - sogar Variablen werden gespeichert!)
...


Sehen Sie sich hier die von Irtron

int ComparePrice(double a, double b, double digit)
{
     a -= b;
     b = digit;
     if (a > b)
         return (1);
     if (a < -b)
         return (-1);
     return (0);
 }

vorgeschlagene Methode an. Sie ist sowohl kompakter als auch schneller als meine, sieht aber schon auf den ersten Blick verdächtig aus, weil der Vergleich zwei Variablen double!!!!

In diesem Schema fungiert nur digit als Konstante und kann verglichen werden, während die Variable a, die ebenfalls verglichen wird, unnormalisiertes Double bleibt!
Erweckt dies Verdacht? (Unter Konstanten verstehe ich übliche Konstanten - "#define" und jene Variablen, die nicht an den Operationen beteiligt waren).

Auch in anderen Zweigen Entwickler selbst schrieb, dass auch Konstanten verdoppeln besser nicht zu vergleichen!!!
Es ist auch nicht richtig, NormalizeDouble(a) zu machen! NormalizeDouble(b), !OC! - Vergleichsoperator!

Zumal in der ursprünglichen Version statt konstanter Ziffern so b = Punkt / 2 war - hier schon zwei von zwei nicht normierten Variablen?

Ich würde gerne glauben, dass diese Variante genial ist, aber zerstreue erst einmal meine Zweifel!

Vielleicht findet ja auch jemand Fehler in meiner Variante?
 
gravity001:

Hier ist ein Blick auf die von Irtron vorgeschlagene Methode

int ComparePrice(double a, double b, double digit)
{
     a -= b;
     b = digit;
     if (a > b)
         return (1);
     if (a < -b)
         return (-1);
     return (0);
 }
Ich habe eine andere Methode vorgeschlagen.
Schauen Sie bitte genauer hin.


Zumal es in der ursprünglichen Version statt der Ziffernkonstante so b = Punkt / 2 war - hier schon zwei der beiden nicht normalisierten Variablen?

Um welche Versionen handelt es sich?

Ich habe Ihnen bereits von der Normalisierung erzählt. Sagen Sie mir zuerst, warum ich es anwenden soll, und dann wie und wo.

Vielleicht wissen Sie zum Beispiel, warum wir Preise mit einer Genauigkeit von 14 Stellen vergleichen sollten, die in der obigen Diskussion als Errungenschaft genannt wird? :) Zur Erinnerung: Die Funktion, die ich vorgeschlagen habe, heißt ComparePrice :)
 

Irtron писал (а):
...
Ich habe eine andere Methode vorgeschlagen.
Schauen Sie bitte genauer hin.
...

Um welche Versionen handelt es sich?

Ich habe Ihnen bereits von der Normalisierung erzählt. Sagen Sie mir zuerst, warum sie angewendet werden sollte, und dann wie und wo.

Vielleicht wissen Sie zum Beispiel, warum wir Preise mit einer Genauigkeit von 14 Stellen vergleichen sollten, die in der obigen Diskussion als eine Art Errungenschaft bezeichnet wird? :) Zur Erinnerung: Die Funktion, die ich vorgeschlagen habe, heißt ComparePrice :)
Hier, ist das Ihrer? Habe ich jetzt richtig zitiert?
Irtron 10.09.2007 04:07

...

int ComparePrice(double a, double b)
{
a -= b;
b = Punkt / 2;
wenn (a > b)
zurück (1);
wenn (a < -b)
zurück (-1);
zurück (0);
}
...
Zur Erinnerung: Die Funktion, die ich vorgeschlagen habe, heißt ComparePrice. :)

Wenn Sie es bemerkt haben, habe ich auch die Funktion ComparePrice zitiert. Nur ist Ihre bereits von der ÖVAG modifiziert worden. Deshalb habe ich mich auf die ursprüngliche Version bezogen, d.h. auf Ihre Funktion!
Ich habe beide Funktionen selbst getestet. Ja, sie haben sich als schneller erwiesen. Doch wie lässt sich die Zuverlässigkeit des Vergleichs überprüfen? Ich bin sehr verwirrt durch den Vergleich von zwei Variablen double. Obwohl alles richtig sein muss, denn es braucht ein Intervall! Dennoch besteht der Verdacht, dass es nicht immer richtig funktioniert!

Ich habe bereits über die Normalisierung gesprochen. Sagen Sie mir zuerst, warum ich es anwenden soll, und dann wie und wo.

Das ist die entscheidende Frage, oder? Ich selbst habe lange darüber nachgedacht: "Man tippt das Doppelte und bekommt das Doppelte ".
Ich habe die genaue Antwort nicht gefunden. Aber ich kann es mir so vorstellen

double a = 2.000000000000
double b = 2,000000000001
double c = 1,999999999999

Alle diese Variablen sind unterschiedlich und werden bis auf die letzte Stelle genau gespeichert!
In diesem Fall definieren wir die Zeichen (Ziffern) selbst. Alles, was nicht definiert ist, wird mit Nullen aufgefüllt.

Wenn wir double a = 2.0 definiert hätten, und es ist im Speicher als 2.0000001 oder 1.9999999 gespeichert, ist es klar, dass NormalizeDouble() nicht helfen würde, weil es einen ungenauen Wert zurückgeben würde!
Ich denke, ein solcher Fehler tritt fast nie auf, wenn man sich einen Variablenwert merkt. Außerdem glaube ich nicht, dass die Zahl 2.0 als 1.9999999999999 gespeichert wird, denn jedes Zeichen (Ziffer oder Punkt) wird mit einem bestimmten Bit in der Bitkette gespeichert! Daher wird die Zahl 2,0 sicher als 2,00000...00 gespeichert.

Der andere Fall ist, dass wir die Zeichen nicht selbst bestimmen:

a = 4.0;
b = 2.0;
c = a / b // - die "Divisions"-Operation wird vom Prozessor oder besser gesagt vom Koprozessor durchgeführt, der den Vorspann mit Zeichen (Ziffern) auffüllt.

Nach der Operation kann es sein:
Am häufigsten:
с = 2.000...0
с= 1.99999999...
с= 2.00000001...

d.h. das Ergebnis weicht oft um einen kleinen Betrag vom wahren Wert ab.

Große Fehler treten sehr selten auf:
с = 2.3

Hier gibt es zwei Erklärungen:
1) Beim Aufruf von a oder b wurde ein Teil der Bitfolge im Speicher beeinflusst, d.h. die Variablen a und b wurden verändert.
2) Bei der "Divide"-Operation ist ein Fehler aufgetreten.

Ich denke, dass 2) am häufigsten vorkommt. Warum ich das nicht weiß. Ich denke, es hat damit zu tun, dass der Co-Prozessor so stark optimiert werden soll, dass er unbrauchbar wird.

Wenn eine Variable mit der Zahl 2.000...00 verglichen wird, schlägt die Gleichheit offensichtlich fehl. Nicht alle Bits werden gleich sein.

Jetzt ist NormalizeDouble() da, um zu helfen!
NormalizeDouble() wird diesen kleinen Fehler "beheben"!
Da der Fehler in den meisten Fällen sehr gering ist, führt das Runden mit einer geringen Genauigkeit immer zum richtigen Ergebnis.

Sehen Sie es einmal so:
Runden Sie die Zahl a = 2.111...11 auf die zweite Stelle.
NormalizeDouble() schreibt 2,11 in eine neue Variable und füllt die verbleibenden Bits mit Nullen auf, nicht mit Einsen!
Ich denke, es wird so aussehen:

double MyNormalizeDouble(double value, int digits)
{
    int factor = MathRound( MathPow(10, digits) ); // factor - это множитель,
                                                      с помощью которого мы из VALUE сделаем целое число
    double result = MathRound(factor * value) / factor;
    
    return(result);
}
Hier habe ich versucht zu erklären, warum NormalizeDouble() benötigt wird.

Bis vor kurzem war ich mit dieser Erklärung völlig zufrieden, habe mich aber kürzlich davon überzeugen lassen, dass dieses Schema nicht immer funktioniert

NormalizeDouble(a, 2) !OC! NormalizeDouble(b, 2) wobei !OC! - ist ein Vergleichsoperator.
Obwohl es nach meinem Verständnis immer funktionieren muss!
Deshalb freue ich mich über jede begründete und verständliche Kritik!
 
gravity001:

Außerdem haben die Entwickler in anderen Threads selbst geschrieben, dass sogar doppelte Konstanten besser nicht verglichen werden sollten!!!
Das ist neu für mich! Das nennt man eine sachliche Frage!
Wenn Sie können, geben Sie mir bitte einen Link!

Ich habe eine Frage an die Entwickler:

Erläutern Sie bitte, welche Einschränkungen oder möglichen Probleme beim Vergleich von Doppelwerten mit Konstanten bestehen:
1.
double a=1.23456789;
doppeltes b;

wenn(a>b) oder wenn(a<b)

Und zwar in dieser Form:
2.
#define a 1.23456789;

doppeltes b;

wenn(a>b) oder wenn(a<b)
 
gravity001:

Zumal die ursprüngliche Version b = Punkt / 2 anstelle von konstanten Ziffern hatte - hier schon zwei von zwei nicht normalisierten Variablen?

Deshalb habe ich b = Punkt / 2 durch eine Konstante ersetzt (1.weniger Operationen - höhere Geschwindigkeit 2.explizite konstante Übertragung - höhere Zuverlässigkeit)

Aber angesichts Ihrer Aussage über die Unzuverlässigkeit des doppelten Konstantenvergleichs ist der ganze Sinn verloren. Wir müssen uns mit dieser Frage genauer befassen.

Ich frage mich, was die Entwickler dazu sagen werden.
 
VBAG писал (а):
...
Das ist neu für mich! Das nennt man eine substanzielle Frage!
Wenn Sie können, geben Sie mir bitte einen Link!
...
Ja, ich habe den Link gesucht, wollte ihn sofort einfügen, aber ich konnte ihn nicht finden! Ich erinnere mich, es irgendwo gesehen zu haben, aber es gab so viele solcher Themen. Ich habe auch eine Reihe von Themen in anderen Foren und Büchern zu diesem Thema gelesen.
Ich erinnere mich, dass jemand irgendwo geschrieben hat, aber ich weiß nicht mehr, wo(((((. Wahrscheinlich war es also nicht richtig von mir zu schreiben: "in anderen Threads, die die Entwickler selbst geschrieben haben"!
Ich bitte um Entschuldigung.
Aber wenn ich den Link finde, werde ich ihn sicher posten.

Ich glaube, ich habe es in einem Buch über C++ gelesen. Darin wird beschrieben, wie man reelle Zahlen vergleicht, und es wird gesagt, dass es am besten ist, zu ganzen Zahlen überzugehen!
 
gravity001:
VBAG schrieb (a):
...
Das ist neu für mich! Das nennt man eine substanzielle Frage!
Wenn Sie können, geben Sie mir bitte einen Link!
...
Ja, ich habe den Link gesucht, wollte ihn sofort einfügen, habe ihn aber nicht gefunden! Ich erinnere mich, es irgendwo gesehen zu haben, aber es gab so viele solcher Themen. Ich habe auch eine Reihe von Themen in anderen Foren und Büchern zu diesem Thema gelesen.
Ich erinnere mich, dass jemand irgendwo geschrieben hat, aber ich weiß nicht mehr, wo(((((. Wahrscheinlich war es also nicht richtig von mir zu schreiben: "in anderen Threads, die die Entwickler selbst geschrieben haben"!
Ich bitte um Entschuldigung.
Aber wenn ich den Link finde, werde ich ihn sicher posten.

Ich glaube, ich habe es in einem Buch über C++ gelesen. Darin wird beschrieben, wie man reelle Zahlen vergleicht, und es wird gesagt, dass es am besten ist, zu ganzen Zahlen überzugehen!
Vielen Dank für Ihre Teilnahme und Hilfe. Leider habe ich keinen akademischen Hintergrund in der Programmierung. Ich muss also mehr zuhören und auswendig lernen. Ich hoffe, die Entwickler werden antworten und meine Frage klären.
Ich habe eine Frage an die Entwickler:

Bitte klären Sie, welche Einschränkungen oder möglichen Probleme beim Vergleich von Dubs mit Konstanten bestehen:
1.
double a=1.23456789;
doppeltes b;

wenn(a>b) oder wenn(a<b)

Und zwar in dieser Form:
2.
#define a 1.23456789;

doppeltes b;

wenn(a>b) oder wenn(a<b)
 
Solche Probleme - 1,3333+0,0004 != 1,3337
 

Dieses Gespräch scheint sich endlos fortzusetzen. Wenn ein neuer Benutzer erst einmal Erfahrungen und Kenntnisse gesammelt hat, stößt er in der Regel mehrmals auf die Normalisierung.

Vielleicht ist es im MT5 sinnvoll, die Genauigkeit von reellen Zahlen bei Vergleichsoperationen zwangsweise zu begrenzen, z.B. auf 8 Dezimalstellen (d.h. die Ausführung von NormalizeDouble() mit digit=8 zu erzwingen). Und nur wenn die Funktion NormalizeDouble() explizit angegeben ist, führen Sie die Normalisierung gemäß den darin angegebenen Parametern durch. In diesem Fall wird die Frage viel seltener auftauchen, nämlich nur dann, wenn der Benutzer genau die angegebene Genauigkeit benötigt. Meiner Meinung nach ist dieser Schwanz ein bisschen, aber immer noch süßer als ein Radieschen.

 
VBAG:
Hallo!
Wie Sie wissen, hängt nicht nur die Korrektheit der Berechnungen, sondern auch die Zuverlässigkeit des von Ihnen geschriebenen Codes von der Art der Programmierung und der Genauigkeit des Codes ab.
Wir schreiben kein Spielzeug und deshalb ist die Zuverlässigkeit des geschriebenen Programms die allererste Voraussetzung. Die meisten Berechnungen werden in Dubles durchgeführt, und ein korrekter Vergleich von zwei realen
von zwei reellen Zahlen im Programmcode erfordert eine bestimmte Vorgehensweise und Genauigkeit.
Ich versuche, den "richtigen" Programmierstil herauszufinden, daher die Frage:

Für einen Ausdruck

Doppel-A;
doppeltes b;

if(a==b) oder if(a!=b)
{......} {.... ..}

die Entwickler empfehlen dies
//+------------------------------------------------------------------+
//| Funktion zum Vergleich zweier reeller Zahlen.
//+------------------------------------------------------------------+
bool CompareDouble(double Zahl1, double Zahl2)
{
bool Compare = NormalizeDouble(Number1 - Number2, 8) == 0;
return(Compare);
}
//+------------------------------------------------------------------+


Ist dieser Code korrekt?

Doppel-A;
doppeltes b;

if(a>b) if(a<b)
{......} {......}


Höchstwahrscheinlich nicht im allgemeinen Fall. Wie kann man das richtig überprüfen?
Welche Art der Arbeit mit Dubles ist im Allgemeinen besser geeignet?
Vielen Dank im Voraus an alle, die geantwortet haben.

Du hast alles durcheinander gebracht... :)

Der Vergleich von Gleitkommazahlen erfolgt durch den Vergleich des Differenzmoduls mit einem kleinen Schwellenwert.

Rückgabe (fabs(d1-d2) < 1e-10) zum Beispiel.

Was bringt es, die Dinge durcheinander zu bringen... Die Funktion NormalizeDouble(...) ist nur für hübsche Berichte gedacht.

Grund der Beschwerde: