Borland Feature oder Implementierung in C++ (long double Verhalten)?
-
float f11=1.2345674; float f12=1.2345670; float f13=f11-f12; //f13 = 3.576279E-07 float f14=1.2345674 - 1.2345670; //f14 = 4E-07 double d15=f13-f14; //wie erwartet ungleich Null float f21=1.2345674F; float f22=1.2345670F; float f23=f21-f22; //f23 = 3.576279E-07 float f24=1.2345674F - 1.2345670F; double d25=f23-f24; //wie erwartet gleich Null long double ld31=1.2345678901234567; long double ld32=1.2345678901234560; long double ld33=ld31-ld32; //warum wird auf der rechten Seite nur mit double gerechnet? //ld33 = 6.66133814775093888E-16 long double ld34=1.2345678901234567 - 1.2345678901234560; double d35=ld33-ld34; //gleich Null long double ld41= 1.2345678901234567L; long double ld42= 1.2345678901234560L; long double ld43=ld41-ld42; //ld43 = 6.99960922556641664E-16 long double ld44=1.2345678901234567L - 1.2345678901234560L; double d45=ld43-ld44; //wie erwartet gleich Null;
Warum wird bei "ld33=ld31-ld32" auf der rechten Seite nur mit double gerechnet und warum wird dies konsequenterweise nicht auch mit "f13=f11-f12" gemacht? Ist das nach C++ Standard so oder nur ein Feature von Borland C++ Builder 6?
-
Schnuckelhase schrieb:
float f11=1.2345674;
Warum ...
Schnuckelhase,
ich habe Deinen Quellcode nicht wirklich analysiert, aber die meisten Deiner eingetippten reellen Zahlen kann der Computer vermutlich gar nicht exakt(!!!) darstellen. Daher sind auch Deine Berechnungen eher Glückssache.
Bitte bedenke: Die Menge der reellen Zahlen ist (überabzählbar) unendlich. Die Menge der im Datentpy float darstellbaren Zahlen hingegen ist endlich. Daher werden die meisten Deiner Zeichenketten-Repräsentationen von reellen Zahlen, die Du mal einfach so in Deinen Code eingibst, gerundet.
(vermutlich wird dieser Thread bald irgendwohin verschoben)
-
Sorry, float war eine Stelle zu viel. Jetzt stimmt es:
float f11=1.234564; float f12=1.234560; float f13=f11-f12; //f13 = 3.933907E-06 float f14=1.234564 - 1.234560; //f14 = 4E-07 double d15=f13-f14; //wie erwartet ungleich Null float f21=1.234564F; float f22=1.234560F; float f23=f21-f22; //f23 = 3.933907E-06 float f24=1.234564F - 1.234560F; double d25=f23-f24; //wie erwartet gleich Null long double ld31=1.2345678901234567; long double ld32=1.2345678901234560; long double ld33=ld31-ld32; //warum wird auf der rechten Seite nur mit double gerechnet? //ld33 = 6.66133814775093888E-16 long double ld34=1.2345678901234567 - 1.2345678901234560; double d35=ld33-ld34; //gleich Null long double ld41= 1.2345678901234567L; long double ld42= 1.2345678901234560L; long double ld43=ld41-ld42; //ld43 = 6.99960922556641664E-16 long double ld44=1.2345678901234567L - 1.2345678901234560L; double d45=ld43-ld44; //wie erwartet gleich Null
dschensky schrieb:
aber die meisten Deiner eingetippten reellen Zahlen kann der Computer vermutlich gar nicht exakt(!!!) darstellen.
Darum geht es doch gerade!
ich habe Deinen Quellcode nicht wirklich analysiert
Na danke, hilft mir also nicht weiter.
-
Also für Leute, den der kurze Quelltext noch immer zu lang ist:
long double ld31=1.2345678901234567; //ld31 = 1.23456789012345664 long double ld32=1.2345678901234560; //ld32 = 1.234567890123456 long double ld33=ld31-ld32; //warum wird auf der rechten Seite nur mit double gerechnet? //ld33 = 6.66133814775093888E-16 long double ld41= 1.2345678901234567L; //ld41 = 1.23456789012345664 long double ld42= 1.2345678901234560L; //ld42 = 1.234567890123456 long double ld43=ld41-ld42; //ld43 = 6.99960922556641664E-16
Dabei gilt meine alte Frage natürlich weiter:
Warum wird bei "ld33=ld31-ld32" auf der rechten Seite nur mit double gerechnet und warum wird dies konsequenterweise nicht auch mit dem entsprechenden Floatbeispiel gemacht?
-
Schnuckelhase schrieb:
Also für Leute, den der kurze Quelltext noch immer zu lang ist ...
Ah, jetzt habe ich die Frage verstanden. Ich habe mal ein wenig im Stroustrup (Abschnitt 4.5) geblättert:
"Standardmäßig ist ein Gleitkommaliteral vom Typ double."
und weiter
"Wenn man ein Gleitkommaliteral vom Typ long double benötigt, kann man es mit dem Suffix l oder L definieren..."Also, wenn ich das richtig verstanden habe, passieren bei
long double ld31=1.2345678901234567;
zwei Sachen:
1. Eine Konvertierung des Literals in ein double (da liegt das Problem) und
2. bei der Zuweisung eine Konvertierung dieses doubles in ein long double.
Deswegen bekommt man wohl auch einen anderen Wert heraus, wenn man nur mit double arbeitet:double d1 = 1.2345678901234567; //1.23456789012346 long double d2 = 1.2345678901234567; //1.23456789012345669 long double d3 = 1.2345678901234567L; //1.2345678901234567
-
Vielen Dank, so kling es logisch.
Aber dann liegt die Verwirrung am Debugger, der zeigt mir nämlich für ld31 und ld41 bzw. ld32 und ld42 identische Werte an.
d2 und d3 sind bei mir auch anders:
d1: 1.23456789012346
d2: 1.23456789012345664
d3: 1.23456789012345664
-
Schnuckelhase schrieb:
Vielen Dank, so kling es logisch.
Aber dann liegt die Verwirrung am Debugger, der zeigt mir nämlich für ld31 und ld41 bzw. ld32 und ld42 identische Werte an.Ja, ist mir auch aufgefallen, die Kurzhinweise sind irgendwie gerundet. Ich habe die "Watches" (CTRL+Alt+W) benutzt.
-
Ich benutze Borland C++ Builder 6.0 Professionel, überwachte Ausdrücke und/oder lokale Variablen. Schade eigentlich dass der Debugger keine vernünftigen Werte liefert.