Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » ist wirklich der Round-off Error so gross????

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
18.06.2003, 11:10 Uhr
~Davood
Gast


Hallo C++ Experten!
in meinem Programm berechne ich eine Summierung und diese Summirung muss null werden. Aber der Code in C++ gibt einen sehr groben Wert (grob für mich) und zwar 6.50521E-19. Ich habe den Code mit Visaul C++ kompiliert. Das kann aber nicht sein so ein round-off error. Das probelm hatte ich nie in Fortran. Hier unten ist der sehr einfache Code, der die selbe Berechnungen macht: (wenn man diese Berechungen z.B. in Excell ausführt, kommt genau 0.0 als Endwert raus!!!!) Ist es ein algemeines Problem oder muss ich in Compiler eine Option einschalten??? Ich hoffe, dass jemand mir helfen kann!


#include <stdio.h>
#include <iostream.h>
#include <string.h>
#include <fstream.h>

double gravty = 9.80933;
double x1,x2,x3;
double y1,y2,y3;
double z1,z2,z3;

double h1,h2,h3;

double wse, dt, A, slopX;
double bedSlope1, bedSlope2, bedSlope3;
double pressurX1, pressurX2, pressurX3;
double ResVx = 0.0;

void main()
{
x1 = 6.25e+1, x2 = 6.25e+1, x3 = 6.49999976e+1;
y1 = 1.40000001e+1, y2 = 1.20000005e+1, y3 = 1.20000005e+1;
z1 = 0.0, z2 = 0.0, z3 = 5.0e-1;

wse = 0.8;
dt = 0.001;

h1 = wse - z1;
h2 = wse - z2;
h3 = wse - z3;

A = 0.5 * ((x2*y3-x3*y2)+(x3*y1-x1*y3)+(x1*y2-x2*y1));
slopX = 0.5 / A *(z1*(y2-y3)+z2*(y3-y1)+z3*(y1-y2));

bedSlope1 = gravty * 0.5 * (h1 + h2) / 3.0;
bedSlope2 = gravty * 0.5 * (h2 + h3) / 3.0;
bedSlope3 = gravty * 0.5 * (h3 + h1) / 3.0;

pressurX1 = 0.5 * gravty * 1./3. * (h1 * h1 + h2 * h2 + h1 *h2) *(y1 - y2);
pressurX2 = 0.5 * gravty * 1./3. * (h2 * h2 + h3 * h3 + h2 *h3) *(y3 - y2);
pressurX3 = 0.5 * gravty * 1./3. * (h3 * h3 + h1 * h1 + h3 *h1) *(y1 - y3);

printf(" h1 = %15.12f , h2 = %15.12f , h3 = %15.12f \n", h1,h2,h3);
printf(" A = %15.12f , slopX = %15.12f \n", A,slopX);
printf(" bedSlope1 = %15.12f , bedSlope2 = %15.12f , bedSlope3 = %15.12f \n", bedSlope1, bedSlope2, bedSlope3);
printf(" pressurX1 = %15.12f , pressurX2 = %15.12f , pressurX3 = %15.12f \n", pressurX1, pressurX2, pressurX3);

ResVx -= dt * slopX * bedSlope1;
ResVx += dt * pressurX1 / A;
printf(" ResVx = %15.12e \n", ResVx);

ResVx -= dt * slopX * bedSlope2;
ResVx -= dt * pressurX2 / A;
printf(" ResVx = %15.12e \n", ResVx);

ResVx -= dt * slopX * bedSlope3;
ResVx -= dt * pressurX3 / A;
printf(" ResVx = %15.12e \n", ResVx);
}
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
18.06.2003, 11:30 Uhr
DIO



Das Problem bei double-Variablen wirst du ja sicher kennen. Die müssen mit einem begrenzten Zahlenvorrat bis in die Unendlichkeit abbilden können. Dabei kann die Mantisse auch eine gewisse Länge, die mir leider nicht genauer bekannt ist, nicht übersteigen. Damit summieren sich kleiner Zahlenabbildungsfehler natürlich auf. Und der wert 6.50521E-19 ist für eine Berechnung mit doubles wirklich in Ordnung. Kannst ja mal versuchen mit double - variablen 100000000000000000 + 10 zu berechnen und dann 100000000000000010 wieder zu subtrahieren. Da kommst du auch nie auf Null. In Exel kommt wahrscheinlich Null heraus weil der sich sagt der Wert ist so klein das da schon Fehler mitdrin sind ich nehme Null als Ergebnis an.

Das ist mein bescheidenes Wissen zu dem Prob. Wenn mich jemand berichtigen kann, wäre ich sehr zu Dank verpflichtet.

MFG DIO
--
Wie einst ein großer Mathematiker sagte:
Wir müssen wissen - Wir werden wissen
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
18.06.2003, 11:30 Uhr
virtual
Sexiest Bit alive
(Operator)


Schau mal diesen Thread:www.fun-soft.de/index.php?file=/forum/showtopic.php?threadid=2759&time=1055928478
rundungsfehler dieser Größenordnung sind nichts ungewöhnliches, du solltest es vielleicht mal mit einem long double probieren, welches ggf. eine höhere Genauigkeit aufweist.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
18.06.2003, 11:32 Uhr
~0xdeadbeef
Gast


Was heißt so groß? Ich finde, 6.5 * 10^-19, oder 0.00000000000000000065 ist nun wirklich nicht sonderlich viel...
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
18.06.2003, 11:35 Uhr
virtual
Sexiest Bit alive
(Operator)


@beefy
Das kommt ein wenig auf den Anwendungsfall an, würde ich sagen. In C++ kann man sich aber auch ein C++ Klassen schreiben oder aus dem Netz ziehen, die super genau arbeiten und sich ziemlich nahtlos in das Programm einarbeiten lassen. Mit og Link habe ich gute erfahrungen gemacht.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
18.06.2003, 11:40 Uhr
DIO



http://cplus.kompf.de/artikel/gmp.html

Diese Seite gibt einen kleinen Einblick in das Mantissenproblem, und bietet anscheinend sogar eine Lösung an... Damit habe ich mich aber nicht weiter beschäftigt

MFG DIO
--
Wie einst ein großer Mathematiker sagte:
Wir müssen wissen - Wir werden wissen
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
18.06.2003, 11:55 Uhr
~0xdeadbeef
Gast


@virtual: Auch wieder wahr. Allerdings benutzt du, wenn du derart feine Auflösungen brauchst, keinen 32-bit-Prozessor.

@DIO: Die Lösung ist Rechnen mit Strings. Das ist zwar sehr genau, aber auch sehr rechenaufwändig, und dementsprechend nicht immer die bessere Wahl.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
18.06.2003, 12:00 Uhr
DIO



Da hatte doch mal der eine Superchecker im C-Golf-Thread die Informatikerfrage gestellt von wegen rechen durch Textersetzung,
(123 + 456 = ? --wird zu--> 123 + 456 = 579)

ich glaube du erinnerst dich. Ist das so ein Ding mit den Strings???

MFG DIO
--
Wie einst ein großer Mathematiker sagte:
Wir müssen wissen - Wir werden wissen
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
18.06.2003, 12:00 Uhr
ao

(Operator)


Was du da beschreibst, ist völlig normal, und die Größenordnung paßt auch. Die Werte, die du in ResVx aufsummierst, sind etwa X * 10^-3. Damit sind bei double 15 bis 16 Stellen weiter rechts Rundungsfehler zu erwarten, d.h. bei 10^-18 oder 10-^19.

Da hilft keine Compileroption, sondern nur eigener Verstand, sprich, sinnvolles Runden.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
18.06.2003, 12:04 Uhr
~0xdeadbeef
Gast


@DIO: Nicht wirklich. Was der wollte, beschränkte sich auf dreistellige Zahlen und war ein unglaublich ineffizientes Ding. Wenn du wissen willst, wie die GNU-Leute das machen, schau in den Sourcecode der GMP. Die kriegen das im Zweifel schon ganz gut hin.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: