Bibliotheken: Math Utils - Seite 6

 
Wenn Sie eine benutzerdefinierte Funktion benötigen, um genau die gleiche kürzeste Zeichenkette zu erhalten wie der Cast (string)dbl, verwenden Sie bitte die Funktion Repr() in der Bibliothek:

string shortest_str = Repr(dbl) .

Diese Funktion wurde früher benötigt, bevor die MQL-Entwickler den Fehler mit string und Print() behoben haben, um dem ieee-754-Standard zu entsprechen.
 

Ich wünschte, du hättest Recht und es wäre so einfach. Ich wäre nicht hier, wenn es so einfach wäre, und würde bestimmt nicht so viele Arbeitsstunden damit verschwenden.


Es stimmt, dass ich Folgendes tun muss:

1. die Anzahl der Stellen nach dem Komma kontrollieren

2. die Anzahl der Ziffern dynamisch anpassen und sie so kurz wie möglich machen


Meine Doubles kommen von

Tickwert -> SYMBOL_TRADE_TICK_VALUE

TickGröße -> SYMBOL_TRADE_TICK_SIZE

und

LotValue = ((TickValue / TickSize) * lot);


Nichts Seltsames, Standardwerte, alles gut, aber LotValue scheint schwer zu formatieren und auf dem Bildschirm zu zeigen zu sein.


Das große Problem ist, dass meine Doubles als 1.000000000 angezeigt werden, aber sie sind eigentlich 1.000000001

(Ich weiß, wie Doubles funktionieren, und verstehe, dass das normal ist)


Print(), DoubleToString(), NormalizeDoubles() und StringFormat() runden grundsätzlich die Zahl und die resultierende Zahl ist schrecklich falsch; nichts funktionierte, die gewünschte Genauigkeit war einfach nicht erreichbar mit eingebauten MQL4-Funktionen, weil sie die Zahl runden, und 1.000000000 endete gleich 1.1

(ich kann mir nicht vorstellen, dass es für eine Anwendung, die ständig Preise anzeigt, praktisch ist, eine "gefälschte" Zahl zu sehen, die von 1,04966 in 1,0497 umgewandelt wird, aber das ist eine Diskussion für einen anderen Tag)


Deshalb habe ich zunächst eine einfache Formel verwendet, um die gewünschte Genauigkeit zu erreichen

int p = 5; // gewünschte Genauigkeit

double n = 1.000000000;

double p10 = (p * 10);

double(long(n * p10) / p10);

Aber die Sache wird komplizierter, wenn es sich nicht um Forex, sondern um Crypto handelt, wo ich eine höhere Genauigkeit von 9-10 benötige, und darüber hinaus war ich nicht in der Lage, die nachgestellten Nullen zu entfernen, also kam ich zu Ihren Funktionen.

Und all diese Schwierigkeiten, weil ich dem Benutzer so viele Informationen wie möglich ausgeben muss und der Platz auf dem Bildschirm begrenzt ist, weshalb ich die Zahl in einen festen Platz quetschen muss.


Ihre Funktion Trunc() erfüllt den Zweck für 99,9 % der Zahlen, aber es gibt einige, die nicht kooperieren und eine Sonderbehandlung benötigen.

Ich hatte gehofft, Sie könnten eine reduzierte Formel dafür angeben.


Und jetzt kommt zu meinen Problemen noch hinzu, dass die Funktion Round(double, int) die MT4-Ausführung bei einigen Doubles stoppt. Ich kann nicht herausfinden, warum, das Double ist nicht so groß, nämlich 100000.0000000000

Es ist eine gewöhnliche Zahl, die den Wert von 1 Lot für EURUSD darstellt, und wenn ich den Wert von Hand schreibe, ist alles in Ordnung, aber wenn er aus der Mathematik kommt LotValue = ((TickValue / TickSize) * lot); MT4 blockiert.


So eine einfache Aufgabe und ich habe bereits 40+ Stunden damit verbracht. Es bringt mich um!!

 
Cristian Dan Fechete #:

Es ist wahr, dass ich das muss:

1. die Anzahl der Stellen nach dem Dezimalpunkt kontrollieren

2. die Anzahl der Ziffern dynamisch anpassen und so kurz wie möglich machen


Ich habe Ihnen gesagt
double n = 1.000000000;
Ist dasselbe wie:
double n = 1.0;

Ihre Anforderung:
Dezimalstellen in der Zeichenkette <= specified_digits

Wenn Ihre einzige Anforderung darin besteht, die Zahl in eine möglichst kurze Zeichenkette ohne nachgestellte 0 zu formatieren (und dabei die maximale Anzahl der Dezimalstellen zu kontrollieren):

string s1 = (string) Round(number, digits);

string s2 = (string) NormalizeDouble(number, digits);

string s3 = StringFormat("%.5f", number);
Wählen Sie eine beliebige Form von ihnen.

Round, und NormalizeDouble wird die maximale Dezimalstellen zu kontrollieren. Die Umwandlung in eine Zeichenkette (string)dbl ergibt dann die kürzestmögliche Zeichenkette ohne die nachgestellten Nullen. StringFormat() tut dasselbe, scheint aber etwas langsamer zu sein, wenn es in Ihrem Code millionenfach aufgerufen wird.

In Ihrem Fall ist DoubleToString() nicht ratsam, da es die kürzeren Strings < Ziffern mit nachgestellten 0en auffüllt, um eine feste Anzahl von Dezimalstellen zu erhalten. Das ist nicht das, wonach Sie fragen. Sie fragen nach einer dynamischen Anzahl von Dezimalstellen (die kürzeste).

Bearbeiten:
Sie berechnen die Genauigkeit falsch als
int p = 5; // gewünschte Genauigkeit
double p10 = (p * 10);

Sie sollte berechnet werden als:
int p = 5; // gewünschte Genauigkeit
double p10 = MathPow(10, p);

 

Es scheint, dass ich nach 4 Nachrichten nicht in der Lage war, Ihnen mein Problem verständlich zu machen, und ich fühle mich schrecklich enttäuscht von meinem Versagen.

Außerdem ist der Stylizer auf dieser Website völlig fehlerhaft, so dass es sehr zeitaufwendig ist, eine Nachricht hier richtig zu schreiben

double n = 1.000000000; 
should be the same as:
double n = 1.0;
but it is NOT

Ich kann nicht erklären, warum, aber wir müssen davon ausgehen, dass 1.000000000; irgendwo eine andere Dezimalstelle als 0 hat, obwohl ich es grafisch nicht ausgeben konnte.

Aber die Ergebnisse sind so:

string s1 = (string) Round(number, digits);  -> blocks MT4

string s2 = (string) NormalizeDouble(number, digits); -> returns a 'faked' string where a rounding is done on last digit

string s3 = StringFormat("%.5f", number); -> same as NormalizeDouble()

für Zahlen wie 19.65400

string s = (string) Trunc(number, digits);

funktioniert es perfekt. Und wenn ich manuell 1,0000000 eingebe, funktioniert es immer noch perfekt.

Nur damit Sie mich verstehen, ich verwende die Funktion für mehr als 400 verschiedene Parameter und jeder von ihnen hat bei jedem Tick einen anderen Wert und Trunc() funktioniert perfekt.

Aber für:

double lotValue = ((_TickValue / _TickSize) * lot);

Das tut es nicht, und deshalb habe ich auch die Funktion Round(number, digits); eingebaut, und das hat auch funktioniert, und ich habe beschlossen, Sie einfach zu fragen, ob es eine Formel gibt, um meine Funktion Normalize_Double_ToString() in einem einfacheren und optimierten Code zu kombinieren.

Und Sie haben mir etwas ganz anderes geantwortet (ich nehme an, dass es ganz allein meine Schuld ist, weil ich es nicht richtig erklärt habe)

Aber seit gestern blockiert Round() MT4, und ohne Round kann ich die Significant Digits auf der Dezimalseite nicht richtig zählen.

Das Problem scheint das Typecasting zu long zu sein. Wenn ich es aus Round(double, int); entferne, führt MT4 ohne Probleme aus, aber dann kann ich nicht herausfinden, wie ein Double mit 6 ganzen Ziffern, multipliziert mit 10000, die Grenzen von Long erreicht.


Ich schätze, an diesem Punkt ist meine Frage:

Wo ist der Ausgang?


Wie auch immer, ich werde es dabei belassen und in ein paar Wochen darauf zurückkommen.

 

Versuchen Sie dies:

string Normalize_Double_ToString(double n, int d)
{
   n = Round(n, d);
   d = MathMin(d, GetDigits(n);

   return DoubleToString(n, d);
}

Allerdings wird es nicht viel besser sein als die 3 kürzeren Methoden im vorherigen Beitrag.

Hinweis,

Ich verwende Round() aus meiner Bibliothek, nicht die falsche Methode, die Sie zuvor gepostet haben, oder verwenden Sie stattdessen:

n = NormalizeDouble(n, d);

Aber ich bezweifle, dass Round() Fehler hat.
 
Cristian Dan Fechete #:

Es scheint, dass ich nach 4 Nachrichten nicht in der Lage war, Ihnen mein Problem verständlich zu machen, und ich bin furchtbar enttäuscht über mein Versagen.

Und der Stylizer auf dieser Website ist völlig fehlerhaft, so dass es sehr zeitaufwendig ist, eine Nachricht hier richtig zu schreiben

Ich kann nicht erklären, warum, aber wir müssen davon ausgehen, dass 1.000000000; irgendwo eine andere Dezimalstelle als 0 hat, obwohl ich es grafisch nicht ausgeben konnte.

Ich bin sicher, dass ich die Ursache für Ihre Probleme mit MT4 verstehe.

Der Hauptgrund dafür, dass Sie nicht die erwarteten Ergebnisse erhalten, ist ein Fehler in MQL4's string(dbl), der auf MT4 noch nicht behoben ist.

Fehler in MQL4 string() Funktion. Falsche Umwandlung von double -> string.

Dies wirkt sich auch darauf aus, wie Double (durch implizites Casting in String) von Print(), Alert(), Comment(), FileWrite() angezeigt wird.

Der Fehler wurde auf MT5 behoben, aber nicht auf MT4. Siehe hier: https: //www.mql5.com/en/forum/367839/page3#comment_27477157 und der Fix hier: https: //www.mql5.com/en/forum/367839/page5#comment_27613205

Meine Empfehlung:

Wenn Sie tiefer graben oder Ihre Doubles als String in MT4 debuggen wollen, dann erzwingen Sie immer eine explizite Umwandlung in String über die Funktion Repr() aus math_utils.mqh

#include "math_utils.mqh"

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void OnStart()
  {
   double a = 1.0000000000000002;
   Print(a);         // 1.0 (Fehler beim impliziten Cast double -> string)
   Print(Repr(a));   // 1.0000000000000002

   double b = 100.00000000000003;
   Print(b);         // 100,0 (Fehler beim impliziten Cast double -> string)
   Print(Repr(b));   // 100.00000000000003
  }
MT5/mql5 reported and confirmed bugs. - Custom ZERO Level Showing ZERO level, bug in MML. String(MQ)
MT5/mql5 reported and confirmed bugs. - Custom ZERO Level Showing ZERO level, bug in MML. String(MQ)
  • 2022.02.01
  • Alain Verleyen
  • www.mql5.com
On indicators, mt5 can set automatically a level "0" depending of the buffer values. Custom indicator showing zero level, though not defined anywhere in the code. Wrong conversion of double -> string. Then test the same example in your browser js pad or any online javascript pad and check the difference