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

 
Nikolai Semko:

Ich habe bereits hier darüber geschrieben.

Ok. wie ich verstehe, schreiben Sie innerhalb dieses Terminals und innerhalb der gegebenen Genauigkeit, Sie sind nicht daran interessiert, den Code auf ein anderes Gerät oder eine andere Plattform zu portieren und auszuführen.

Mit freundlichen Grüßen.

P.S. Ein guter Programmierer sollte sich darüber im Klaren sein, dass sich die Hardware und das Programm ändern können und dass man Fehler in der Zukunft vermeiden muss.
 
Andrey Kisselyov:
Wenn Sie innerhalb der Grenzen des gegebenen Terminals und innerhalb der Grenzen seiner Genauigkeit schreiben, ist die Portierung und der Betrieb des Codes auf einem anderen Gerät oder einer anderen Plattform für Sie nicht von Interesse.

Mit freundlichen Grüßen.

Ganz genau. Wir sprechen hier von MQL5 (vielleicht auch MQL4 - ich habe es nicht überprüft). Und der Code in den Klassen oder Algorithmen lässt sich perfekt in MQL übertragen. Es funktioniert aber auch in C++. Ich habe bereits einige Beispiele.

 
Andrey Kisselyov:

P.S. Ein guter Programmierer muss sich darüber im Klaren sein, dass sich die Hardware und das Programm ändern können und dass es notwendig ist, Fehler in der Zukunft zu vermeiden. Bei einer Aufgabe wie der Ihren wird es Ihnen in der Zukunft nicht leicht fallen, einen Fehler in einer Funktion zu finden, die Sie zu diesem Zeitpunkt für unfehlbar halten.
In dieser Situation ist es unmöglich, sich die Veränderungen, von denen Sie sprechen, auch nur vorzustellen. Was könnte sich an der Mathematik der Berechnung von (int)(x+0,5) ändern? Wird es aufhören, den Bruchteil zu verwerfen oder was?
 
Nikolai Semko:
In dieser Situation ist es unmöglich, sich die Veränderungen, von denen Sie sprechen, auch nur vorzustellen. Was kann sich an der Mathematik der Berechnung von (int)(x+0,5) ändern? Wird es aufhören, den Bruchteil zu verwerfen?

Zum Beispiel wird ein neuer Datentyp eingeführt ...

 
STARIJ:

Zum Beispiel wird ein neuer Datentyp eingeführt ...

))) Ja, aber der Code wird nicht mehr funktionieren, wenn der alte Datentyp gelöscht wird....
 
Ich spreche von diesem Schlamassel.
y=(int)(x+0.9999999999999997);

Nehmen wir als Beispiel:
Wenn Sie sogar die Bittiefe der Maschine ändern, d.h. auf 64 Bits wechseln und die Genauigkeit der Maschine gestiegen ist, wird Ihre Formel nicht mehr funktionieren, da die Genauigkeit der Maschine viel höher sein wird als die, die Sie in Ihrem Fehler eingestellt haben.

Mit Verlaub.

P.S. es kann andere Optionen geben, wo Ihre Formel auf einer Reihe von Zahlen scheitern wird. ständig Anpassungsfehler von der Umstellung auf eine andere Maschine, oder Änderungen in Compiler, die Sie nicht informiert sind, oder wenn Sie die Darstellung von Zahlen in der Maschine ändern, oder vom Schneiden eines gebrochenen Teils der Zahl beim Kompilieren einer neuen Version des Terminals ... Man weiß nicht, was sich ändern kann, und ich halte es nicht für eine gute Idee, ein IF zu machen oder zu erraten, was passieren wird, indem man einen Fehler immer wieder schreibt...

Ich denke, das ist eine Überlegung wert.

 
Andrey Kisselyov:

...

P.S. double kann per Definition keine ganze Zahl sein, die Darstellung einer Zahl im Maschinenspeicher wird sich nicht ändern.

Vielleicht wollen Sie damit sagen, dass double kein ganzzahliger Datentyp ist, und nicht, dass man eine Zahl mit einem ganzzahligen Wert nicht in einer Variablen vom Typ double speichern kann? Eine ganze Zahl double kann eine ganze Zahl sein.

 

Ich habe eine einfache Erklärung für den Unterschied zwischen der in Computern implementierten Rundung und der einfachen Abrundung nach dem Stapeln gefunden. Vierzehn Jahre alt, http://delphimaster.net/view/14-10885/all:

Tolik(2003-08-13 11:04) [11].

Eine solche Rundung ist in der Buchhaltung üblich. Das Finanzamt wendet also auch diese Rundung an, so dass sich alles aufaddieren sollte, zumindest auf dem Papier :))



DiamantHai(2003-08-13 11:20) [12]

Oh-ho-ho... Nochmals.
Angenommen, wir haben eine Zahlenverteilung, die annähernd gleichmäßig zufällig ist. Durch "arithmetische" Rundung ergibt sich dann:

Die Zahl Uncertainty
0 0
1 -1
2 -2
3 -3
4 -4
5 +5
6 +4
7 +3
8 +2
9 +1

Es ist leicht zu erkennen, dass bei einer großen Anzahl von Zahlen, die anschließend addiert werden müssen (Summen für Belegpositionen, Kontostände usw.), durch die "arithmetische" Rundung ein systematischer Fehler entsteht, bei dem zu erwarten ist
0,5*10^n * 0,1 * N
wo:
n -- Dezimalgewicht der Stelle, auf die gerundet wird (auf zwei Ziffern n=-2, auf ganze Zahlen n=0, usw.)
0,1 ist die Wahrscheinlichkeit für jede Ziffer
N ist eine Anzahl von Ganzzahlen in einem Array

Um die Fehlerwahrscheinlichkeiten auszugleichen, ist es notwendig, den einzigen unkompensierten (siehe Tabelle oben) Fehler +5 zu kompensieren. Dies geschieht durch künstliche Aufteilung in zwei gleich wahrscheinliche +5 -5 je nach der Parität der vorherigen Ziffer.

Übrigens gibt es im FPU-Statuswort ein Kontrollkästchen, das den Rundungsmodus (arithmetisch/buchhalterisch) steuert.


Zitat Ende.

Ein anderer, http://delphimaster.net/view/15-1340952214/all:"da der durchschnittliche Benutzer (Manager/Buchhalter) nicht erklären kann, warum das Runden von 12,5 und 13,5 - unterschiedliche Ergebnisse ergibt."


Wenn dem Benutzer "beschleunigte" Versionen von Rundungsfunktionen zur Verfügung gestellt werden, muss dringend davor gewarnt werden, dass sie zu einem erhöhten Fehler beim Addieren führen. Dieser Fehler muss in sehr unterschiedlichen Situationen sorgfältig geprüft werden. Das ist gefährlich und birgt die Gefahr einer Fehlerhäufung. Es fällt mir schwer, mir ein Beispiel vorzustellen, bei dem das Runden so wichtig ist, dass man die Fehler, die dabei entstehen, vergessen kann.

Округление чисел. Неужели ТАК правильно???
  • delphimaster.net
3-10545           Kati                  2003-08-12 10:13  2003.09.04   обновление SQL запроса 14-10898          kalishenko            2003-08-14 20:09  2003.09.04   Win2000 Server и доступ в Интернет 1-10692           lww                   2003-08-20 10:30  2003.09.04   Как написать dll для 1С? 1-10813           koks                  2003-08-20...
 

Andrey Kisselyov:
я говорю про вот это безобразие

y=(int)(x+0.9999999999999997);

In Ordnung, meine Herren, Sie haben sich klar ausgedrückt. Ich werde die Funktion ceil für Sie ändern:

y=ceil(x);  ->  y=(x-(int)x>0)?(int)x+1:(int)x;
или через дефайн:
#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x

Diese Variante ist 25-50% langsamer als die Variante:y=(int)(x+0.9999999999999997); aber sie ist maximal korrekt, funktioniert für negative ganze Zahlen und ist dreimal schneller als ceil(x).

Aber ich selbst, als Gewöhnlicher und Gescheiterter, werde die Variante mit den Neunen verwenden, weil ich alle Ihre Argumente für langweilig halte und für mich, der ich lange in Assembler programmiert habe und daher weiß, was mit dem Code nach der Kompilierung passiert, ist es zu viel - Prüfungen dort einzubauen, wo man sie entbehren kann.

 

Eine Variante für positive und negative Zahlen:

#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x
#define _round(x) (x>0)?(int)(x+0.5):(int)(x-0.5)
#define _floor(x) (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x
Dies scheint ein vollwertiger Ersatz für ceil(),round(),floor() zu sein, was einen Geschwindigkeitsvorteil von 3-4 mal bedeutet.