Inhalte aufrufen

  • Über WindowsLive anmelden Log In with Google Anmelden
  • Mitglied werden
Profilbild

MathMod() - Bug oder ...?

- - - - -

  • Du kannst leider keine neuen Themen eröffnen
  • Please log in to reply
9 Antworten zu diesem Thema

  #1
OFFLINE   traderdoc

Warum ergibt

 

double a = 0.2;
double b = 0.05;
Alert(MathMod(a, b)); 

 

richtigerweise den Wert 0.0

 

aber bei

 

double a = 0.25;
double b = 0.05;
Alert(MathMod(a, b));

 

den Wert 0.0499999999999999

 

Es kann auch nicht daran liegen, dass die Division zweier double-Zahlen häufig einen Rest in der 6-9. Stelle nach dem Komma ergibt, da MathMod() ja genau das ermitteln soll

und bei 0.2/0.05 ergibt nun mal 4.0 mit Rest 0.0 und nicht 0.04999999999999! Stünde da 0.05 als Ergebnis wäre das auch nicht besser (korrekter).

 

Kurioserweise ergibt wiederum

 

double a = 0.3;
double b = 0.05;
Alert(MathMod(a, b));

 

auch 0.04999999999999999

 

aber

 

double a = 0.4;
double b = 0.05;
Alert(MathMod(a, b)); 

 

wiederum den Wert 0.0

 

Wo liegt der Fehler?

 

traderdoc


Ich erfülle Euch gern Eure EA-, Indikator- und Script-Programmierwünsche.

  #2
OFFLINE   CashDigger

Der normale mathematische Begriff "Rest" gilt eigentlich nur für die Ganzzahldivision. Daher haben diese double Funktionen besondere "Zusätze" die auch das Rechnen mit floats ermöglichen. Das Problem, leider folgen sie nicht den Rundungsregeln der Ganzzahldivision. Also stimmt schon, man könnte von Bug sprechen oder zumindest von einer der vielen Stolperfallen mit floating point Variablen was der Grund für diese Sache ist.
Das gleiche Problem hat man exakt auch in Standardfunktionen von anderen Programmiersprachen.

Es gibt 2 Möglichkeiten:
1: die Variablen für die Berechnung als integer darstellen und dafür mit einem ausreichend großen int multiplizieren (zB *100).
2: nutze meine Funktion: (den Rückgabewert kann/sollte man dann noch durch NormalizeDouble() schicken)

Please Login or Register to see this Hidden Content

1. hat den Vorteil, es ist performanter und den Nachteil, dass die kleinstmöglich auftretende Zahl vom Input bekannt sein muss um den Multiplikator zu bestimmen.

2. hat den Vorteil, es funktioniert immer korrekt und die kleinstmöglich auftretende Zahl darf unbekannt sein. Kleiner Nachteil, es ist weniger performant.

 

Grüße C$D


Bearbeitet von CashDigger, 15 March 2019 - 02:20 Uhr,

  • traderdoc gefällt das

  #3
OFFLINE   traderdoc

Nun ja, im Sinne der Deklaration der Funktion MathMod():

Please Login or Register to see this Hidden Content

würde ich das teilweise Versagen, wie im Post#1 beschrieben, als Bug bezeichnen. Stünde da

Please Login or Register to see this Hidden Content

wäre das Problem auf Anhieb beseitigt.

 

Ich hatte die Lösung auch durch Multiplikation mit 100 gewählt, zumal die Dezimalzahlen in dem Programm immer nur 2 Kommastellen besitzen.

 

traderdoc


Bearbeitet von traderdoc, 15 March 2019 - 18:39 Uhr,

Ich erfülle Euch gern Eure EA-, Indikator- und Script-Programmierwünsche.

  #4
OFFLINE   CashDigger

Das Interessante ist, dass der normale Modulo Operator % in anderen Sprachen sowieso nur für Integer funktioniert und dann macht man solche "Bug"- Funktionen für floats die nicht verlässlich funktionieren. Daher ist es schon absurd, dass man diese Standardfunktionen überhaupt erstellt.

Genau das Gleiche lässt sich aber auch in C/C++ mit fmod() nachbilden (#include <cmath>) und auch in anderen Sprachen ist das Thema. Ebenso kommen bei Online-Rechnern oft falsche Ergebnisse raus, da sieht man, dass es dieses Problem fast überall gibt mit den Standardfunktionen diverser Sprachen.



  #5
OFFLINE   traderdoc

Ja dann fragt man sich doch, warum diese Funktion nicht prinzipiell in allen Sprachen nur mit Integer-Deklarationen ausgestattet wird.

 

Warum einfacher, wenn es auch kompliziert geht.

 

traderdoc


Ich erfülle Euch gern Eure EA-, Indikator- und Script-Programmierwünsche.

  #6
OFFLINE   CashDigger

Ich glaube das Problem dieser Funktionen ist, dass dort evt. intern mit einem cast von double zu int gearbeitet wird und meine Vermutung ist, dass genau dort der Fehler entsteht weil es nicht sorgfältig umgesetzt wurde. Denn wenn man mit einem solchen cast arbeitet muss man von den Floating-Effekten ausgehen und das beachten.

 

Ich habe jetzt nochmal mit dem Ansatz eine neue Funktion geschrieben die ohne Schleife funktioniert und wo die kleinstmöglich auftretende Zahl aktuell bis zur 10. Stelle abgesichert ist (das könnte man sich bei Bedarf noch anpassen oder auch als Parameter mitgeben). Damit sollten fast alle Anwendungsfälle abgedeckt sein. Performance ist viel besser da ich jetzt mit dem cast-Trick arbeite und dabei aber die Floating-Effekte berücksichtige. Und ich habe auch gleich den Rückgabewert von den Floating-Effekten bereinigt. Das Vorzeichen des Ergebnisses hängt normalerweise vom Vorzeichen von a ab, dies ist ebenso für die Rückgabe berücksichtigt. Viel Spaß damit:

Please Login or Register to see this Hidden Content



  #7
OFFLINE   CashDigger

Für den Fall, dass nie negative Werte verarbeitet werden, geht es ohne Vorzeichenhandling natürlich noch schlanker:

Please Login or Register to see this Hidden Content



  #8
OFFLINE   traderdoc

Also wie immer, viele Wege führen nach Rom.

In meinem Fall würde sich

 

if (MathMod(100*a, 100*b) > 0)

 

als ausreichend erweisen.

 

traderdoc


Ich erfülle Euch gern Eure EA-, Indikator- und Script-Programmierwünsche.

  #9
OFFLINE   CashDigger

Funktioniert dann natürlich nur für diesen Usecase aber so oft hat man mit Modulo meist nicht zu tun.

 

Ich würde es dann sicherheitshalber so machen:

if(NormalizeDouble(MathMod(100*a, 100*b),10) > 0)

So eine double 0 könnte (bei dieser komischen Funktion) evt. mal per 0.00000000000001 als Rückgabewert kommen und dann ist der Operator > ausgehebelt :wink:



  #10
OFFLINE   traderdoc

Ja, da gebe ich Dir Recht. Witzigerweise habe ich festgestellt, dass bestimmte Variablenkombinationen von a und b wie in Post #1 beschrieben zu genau

solchen Rückgabewerten mit 0.0000000001 usw. führten und in dem einen Fall erkannt wurden und im anderen Fall wiederum nicht, was für mich

nun völlig nicht nachvollziehbar war. D.h. steht die 1 an der 8. Stelle bist Du raus!

 

traderdoc


Ich erfülle Euch gern Eure EA-, Indikator- und Script-Programmierwünsche.





0 Benutzer lesen gerade dieses Thema

0 Mitglieder, 0 Gäste, 0 anonyme Nutzer