Geschwindigkeit der Ausführung der Funktionen ceil(),round(),floor() - Seite 4

 
Alexey Navoykov:

DBL_EPSILON hat also 16 Dezimalstellen:2.2204460492503131e-016

Und in Ihrem Fall erhalten Sie tatsächlich eine, da der Unterschied nur 1e-16 beträgt, was 2 Mal weniger als Epsilon ist.


Es funktioniert mit 0,999999999999999997, aber mit 0,999999999999999998 funktioniert es nicht mehr.

 
Nikolai Semko:

Funktioniert ab 0,999999999999999997, aber ab 0,9999999999999998 funktioniert es nicht mehr.


Hier ist ein weiterer Trick:

Y=(int)(x+1-2*DBL_EPSILON);
Print(Y);                             // 3
Y=(int)(x+1-DBL_EPSILON-DBL_EPSILON);
Print(Y);                             // 4
 

Die Zahl 2.2204460492502503131e-016 in Dezimalschreibweise bedeutet die Auflösung des Formats double (https://msdn.microsoft.com/ru-ru/library/6bs3y5ya(v=vs.100).aspx), also

Die kleinste positive Zahl x, so dass x + 1,0 nicht gleich 1,0 ist.

- ist die kleinste positive Zahl, bei der die Addition von 1,0 den Wert der Zahl ändert. Mit anderen Worten, es handelt sich um den relativen Fehler bei der Darstellung einer Zahl. Das heißt, für 16 enthält diese Grenze so viele dezimale Neunen, für 64 am Ende viermal so viel wie 1 und für 8 halb so viel. Wir müssen also diese Genauigkeit berechnen, um die Rundung mit der höchstmöglichen Genauigkeit zu beschleunigen. Es ist unwahrscheinlich, dass diese Berechnungen schneller sind als die Leistung der normalen Rundungsfunktionen. Da MQL es nicht erlaubt, direkt mit Adressen von Zahlen zu arbeiten, werden wir nicht in der Lage sein, Bits einer Ordnung in der Zahl zu nehmen, also werden wir das Analogon der Log-Funktion zur Basis 2 erfinden müssen. Es ist unwahrscheinlich, dass es schnell geht.

Пределы констант с плавающей запятой
Пределы констант с плавающей запятой
  • msdn.microsoft.com
В следующей таблице представлены ограничения на значения констант с плавающей запятой. Эти ограничения также заданы в стандартном файле заголовка FLOAT.H. Ограничения на константы с плавающей запятой КонстантаЗначениеЗначение Количество цифр q, при котором число с плавающей запятой с q десятичными цифрами можно округлить в представление с...
 
Nikolai Semko:

Hier noch eine weitere Besonderheit:

Es stellt sich heraus, dass jede mathematische Operation einen zusätzlichen Fehler einführt, der entweder plus oder minus sein kann. Daher ist es, wie Vladimir sagte, im Allgemeinen notwendig, das Ergebnis zu normalisieren.

 

ceil(), floor() werden wahrscheinlich nicht repliziert, da der Rundungsmodus der FPU nicht von der µl gesteuert werden kann. Das Einzige, was wahrscheinlich mehr oder weniger gut funktionieren wird, ist round(), und das ist nach der Norm nicht exakt. So sieht übrigens das C-förmige round() ungefähr aus:

double round(double x)
{
    fenv_t save_env;
    feholdexcept(&save_env);
    double result = rint(x);
    if (fetestexcept(FE_INEXACT)) {
        fesetround(FE_TOWARDZERO);
        result = rint(copysign(0.5 + fabs(x), x));
    }
    feupdateenv(&save_env);
    return result;
}
 
Um zu verstehen, was Sie hier runden wollen, müssen Sie genau wissen, wie und was bei der Umwandlung des DOUBLE-Formats in das INT-Format verloren geht. In diesem Fall erhalten Sie nur den ganzzahligen Teil, der nach dem Runden übrig bleibt. Folglich werden alle Zahlen mit einer beliebigen Anzahl von Dezimalstellen und alle Nachkommastellen entfernt und nur der ganzzahlige Teil bleibt übrig.
Beispiel:
2.1758716871 -> (int)2.1758716871 = 2
2.0000000001 -> (int)2.0000000001 = 2
2.9999999999 -> (int)2.9999999999 = 2
Dies wird als Präzisionsverlust bezeichnet , wenn eine Zahl neu formatiert wird.
demzufolge
MathFloor(x)  =  (int)(x)
MathCeil(x)   =  (int)(x)+1;
MathRound(x)  =  (int)(x+0.5)

Mit freundlichen Grüßen.
 
Andrey Kisselyov:
Um zu verstehen, was Sie hier abrunden wollen, müssen Sie genau wissen, wie und was bei der Konvertierung des DOUBLE-Formats in das INT-Format verloren geht. In diesem Fall erhalten Sie nur den ganzzahligen Teil, der nach der Abtrunkierung verbleibt. Folglich werden alle Zahlen mit einer beliebigen Anzahl von Dezimalstellen und alle Ziffern nach dem Komma entfernt und nur der ganzzahlige Teil bleibt übrig.
Beispiel: Wenn eine Zahl umformatiert wird, spricht man von einem Präzisionsverlust.
demzufolge

Mit freundlichen Grüßen.

Warum ist es so kompliziert?

MathRound(x)  - >  (int)(x)+(int)(2.*(x-(int)(x)));

Inwiefern ist dies besser als die einfachere Variante?

MathRound(x)  ->  (int)(x+0.5);
 
Alexey Navoykov:

Es stellt sich heraus, dass jede mathematische Operation einen zusätzlichen Fehler einführt, der entweder plus oder minus sein kann. Daher ist es im allgemeinen Fall, wie von Vladimir hervorgehoben, notwendig, das Ergebnis zu normalisieren.


pavlick_:

ceil(), floor() werden wahrscheinlich nicht repliziert, da der Rundungsmodus der FPU nicht über μl gesteuert werden kann. Das Einzige, was wahrscheinlich mehr oder weniger gut funktionieren wird, ist round(), und das ist nicht exakt wie der Standard. So sieht übrigens das C-förmige round() ungefähr aus:


Natürlich haben Sie Recht. Aber ich wiederhole. Für 99,9 % der Aufgaben ist es absolut richtig, die Rundungsfunktionen durch eine alternative und schnellere Variante zu ersetzen, die die Umwandlung von Nachkommastellen in (int) oder (long) verwendet. Ein erfahrener Programmierer muss sich dieser Tatsache nur bewusst sein und sie bei Bedarf anwenden.

Для положительных x:
y=floor(x); -> y=(int)x;
y=ceil(x);  -> y=(int)(x+0.9999999999999997);
y=round(x); -> y=(int)(x+0.5);
 
Nikolai Semko:

Warum ist es so kompliziert?

Inwiefern ist dies besser als die einfachere Variante?

können Sie es auf diese Weise versuchen.

Nikolai Semko:
Ein erfahrener Programmierer muss sich dieser Tatsache nur bewusst sein und sie anwenden, wenn es sinnvoll ist.

Es ist nicht so, dass er es muss, er muss es wissen.

Mit Verlaub.

P.S. Ihre Formel ist nicht für die gesamte Menge der Werte korrekt.
y=ceil(x);  -> y=(int)(x+0.9999999999999997);
siehe meine, ich habe die Runde auf eine Kurzformel aktualisiert, jetzt ist die Liste vollständig und voll funktionsfähig, verwenden Sie sie.
 
Andrey Kisselyov:


P.S.: Ihre Formel gilt nicht für die gesamte Wertemenge.

siehe meine, ich habe die Runde auf eine Kurzformel aktualisiert, jetzt ist die Liste vollständig und voll funktionsfähig, verwenden Sie sie.

siehe oben

wenn x = 3 (eine beliebige ganze Zahl) ist, gibt es einen Stau :))