Probleme mit Funktionen aus math.h - exp() liefert nan, obwohl Argument OK
-
Hallo!
Ich habe einige Probleme mit den Funktionen aus math.h. An einigen Stellen kann ich z.B. nicht mal die wurzel von 9 berechnen:
bs=sqrt(9) liefert dann "nan", obwohl an anderen Stellen im Quelltext eine Zuweisung dieser Art funktioniert. (printf("Wurzel aus 9=%f\n",sqrt(9)); funktioniert auch...)Dann möchte ich eine stückweise definierte Funktion integrieren. Die Funtktion sieht ungefähr so aus:
h(a)=c(a)*g1(a), a<pi/2
h(a)=c(a)*g2(a), a>pi/2das ganze habe ich folgendermaßen realisiert:
a=start; while(a<ende) { if (a<pi/2) g=g1(a); /*Sinngemäß jedenfalls/* else g=g2(a); h=c*g; integ(h); }
Dabei tauchen zweierlei Probleme auf: in einer Funktion werden zwar alle Zwischenwerte (g,h,a) wie erwartet aktualisiert, die while Schleife bricht jedoch trotzdem ab, nachdem der else-Teil genau zweimal durchlaufen wurde.
An anderer Stelle läuft die while Schleife zwar bis zum Ende durch, die Aktualisierung von c(a) liefert aber "nan", ebenfalls nachdem der else-Teil genau einmal durchlaufen wurde. (c(a) enthält hier eine exp() Funktion - deren Argumente sind dann zwar im Wertebereich, das Ergebnis ist aber trotzdem "nan" - wie bei der Wurzel oben...)Ich habe jedenfalls keine Idee mehr, wie ich den Fehlern auf die Schliche kommen soll. Falls also jemandem was einfällt wäre ich sehr dankbar. Ich könnte auch mal ein betreffendes Beispiel posten, aber das wollte ich mir im ersten Beitrag verkneifen, weil´s recht lang würde...
\// Matthias
-
Zu deinem Wurzel problem, das geht nicht bei dir?:
int zahl = 9; float f = sqrt(zahl);
Zum 2. Problem kann ich noch nichts sagen, schneid mal deinen Code einigermaßen zusammen und poste ihn.
-
Tja, mit dem Zusammenschreiben ist das so eine Sache... Wenn ich nämlich die fraglichen Funktionen in eine Datei schreibe, funktioniert alles so, wie ich mir das vorstelle. (Mir ist aber nicht klar, warum) Mir ist das aber eigentlich zu unübersichtlich - so dass ich lieber für jede Funktion eine eigene Datei hätte. (Oder ist das schlechter Stil, für 100 Zeilen Code eine eigene Datei aufzumachen?)
Also noch mal eine kurze Zusammenfassung des Problems: in der while-Schleife in boden.c soll die stückweise definierte Funktion g integriert werden. Wenn ich aber in den zweiten Bereich komme (else), dann bricht die Schleife nach genau 2 weiteren Durchläufen ab.
Mittlerweile habe ich auch festgestellt, dass das Wurzelziehen nur nach diesem mysteriösen Abbruch nicht mehr funktioniert...
Jetzt gibts aber erst mal ein bisschen c-Code: zuerst die Definitionen meiner Strukturen structdef.h:
struct loc_var_rad { double De; /*Ersatzraddurchmesser*/ double zea; /*elastische Ausfederung*/ double z0; /*Anfangseinsinkung*/ double f0; /*Reifeneinfederung*/ double l; /*Latschlaenge*/ double FzB; /*Bodenreaktionskraft*/ double jq; /*Scherweg quer*/ double jl; /*Scherweg laengs*/ double tein; /*Eintrittswinkel Rad-Boden*/ double telein; /*elastische Bodeneinsinkung (Multipass)*/ double telaus; /*elastische Bodenausfederung*/ }; struct glob_var { double dz[4]; /*Gesamteinsinkung*/ double Vf[4]; /*Verhältnis f0/z0*/ double DR; /*Reifendurchmesser*/ double b; /*Reifenbreite*/ double vR; /* ?? */ double dR; /* ?? */ double omega[4]; /* Winkelgeschwindigkeit der Raeder*/ double kc; /*Bodenparameter: Kohaesionsmodul*/ double kphi; /*Bodenparameter: Reibungsmodul*/ double n; /*Bodenparameter: Einsinkexponent*/ double cB; /*Bodenparameter: Bodenelastizitaet*/ double c; /*Bodenparameter: Kohaesion*/ double tanphi; /*Bodenparameter: phi=Reibungswinkel*/ double K; /*Bodenparameter: Tangentenmodul*/ double Mu[4]; /*Umfangsmomente am Reifen*/ double j; /* ?? */ double nB; /* ?? */ double Fz[4]; /*vertikale Reaktionskraefte*/ double FH[4][3]; /*horizontale Reaktionskraefte*/ double iter_konst; /*Iterationskonstante fuer Berechnung von Vf[i]*/ double dphi; /*Integrationsschrittweite fuer Bodendruck*/ double dT; /*Schrittweite bei Integration nach Zeit*/ double pos[3]; /*Position Massenschwerpunkt*/ double v[3]; /*Geschwindigkeit Massenschwerpunkt*/ double jlmax[4]; /*maximaler Scherweg in Laengsrichtung*/ double jqmax[4]; /*maximaler Scherweg in Querrichtung*/ };
Dann meine Hauptfunktion main.c:
#include <math.h> #include "structdef.h" int boden(struct glob_var*, struct loc_var_rad*, int i); int main() { int i=1; struct glob_var global; struct loc_var_rad lokal; global.dz[0]=0.1; global.dz[1]=0.098; global.dz[2]=.13; global.dz[3]=0.094; global.Vf[0]=1.03; global.Vf[1]=1.01; global.Vf[2]=0.98; global.Vf[3]=1.06; global.DR=0.6; global.b=0.17; global.kphi=324532; global.n=0.33; global.kc=194399; global.dphi=0.001; global.cB=2.63e9; while (i<=4) { boden(&global,&lokal,i-1); i++; } return 1; }
Das eigentliche Arbeitstier und Quelle allen Übels ist boden.c:
#include <math.h> #include <stdio.h> #include "structdef.h" #define pi 3.14159265 int int_eul_expl(int,double*,double*,double,double*); int boden(struct glob_var *pglobal, struct loc_var_rad *plocal, int i) { /*****************************************************************/ /*Variablendeklaration*/ double kc=pglobal->kc; double kphi=pglobal->kphi; double n= pglobal->n; double Vf=pglobal->Vf[i]; double dz=pglobal->dz[i]; double cB=pglobal->cB; double Dr=pglobal->DR; double b=pglobal->b; double dphi=pglobal->dphi; double k=kc/b+kphi; double z0,f0; double zea; double pmax; double l; double t1,t2,t3,t4,t5,t6,t7,t8; double De; double x0; double f=0, g=0; double a=0; double tein,telein, telaus; double pi_2; double test; /*************************************************************************/ /*Berechnungen*/ z0=dz/(1+Vf); /*Einsinkung*/ f0=Vf*z0; /*Reifeneinfederung*/ pmax=k*pow(z0,n); /*maximaler Bodenruck*/ zea=pmax/cB; /*elastische Ausfederung*/ printf("%d\n",i); t1=(f0+zea); t2=t1*t1; t3=Dr*dz; t4=dz*dz; l=sqrt(Dr*t1-t2)+sqrt(t3-t4); /*Latschlaenge*/ if (zea!=z0) { /*Mittelpunkt des Ersatzrades*/ x0=l*zea/(zea-z0)*(1-sqrt(1-(1-z0/zea)*(1+z0*(z0-zea)/(l*l)))); } else {x0=l/2;} De=z0+(l-x0)*(l-x0)/z0; /*Ersatzraddurchmesser*/ tein=asin(1-2*z0/De); /*Winelbereiche am Ersatzrad*/ telein=asin(1-2*(z0-zea)/De); telaus=pi/2+acos(1-2*zea/De); t5=De*b/2; t6=sin(tein); t7=De/2; pi_2=pi/2; test=9; test=sqrt(test); printf("test=%f\n",test); a=tein+0.00001; while (a <= telaus) /*Bodenreaktion (vertikal)*/ { if (a<pi_2) { t8=t7*(sin(a)-t6); g=t5*k*sin(a)*pow(t8,n); /*plastischer Bereich*/ printf("IF a=%f, g=%f",a,g); } else { g=t5*cB*sin(a)*(zea-t7*(1-sin(a))); /*elastischer Bereich*/ printf("ELSE a=%f, g=%f",a,g); } int_eul_expl(1,&g,&f,dphi,&a); /*loklen Druck integrieren...*/ printf("f=%f\n",f); } plocal->FzB=f; plocal->z0=z0; plocal->f0=f0; plocal->zea=zea; plocal->De=De; plocal->l=l; plocal->tein=tein; plocal->telaus=telaus; plocal->telein=telein; test=9; test=sqrt(test); printf("test=%f\n", test); return 1; }
und zuguterletzt noch eine Routine zur numerischen Integration int_eul_expl.c:
#include <math.h> #include <stdio.h> double int_eul_expl(int dim, double *g,double *f, double h, double *var) { int i=0; while (i<dim) { *(f+i)+=*(g+i)*h; *(var+i)+=h; i++; } return 0; }
So, das ganze habe ich dann mit
gcc -lm main.c boden.c int_eul_expl.c -o programm
kompiliert und heraus kommt ein Programm, das nicht macht, was es soll... (In der boden.c stehen in der while-Schleife noch ein paar printf() Anweisungen drin, so dass die Ausgabe ziemlich lang wird. Also vielleicht besser in eine Datei umleiten)Wäre toll, wenn mir jemand sagen könnte, wo ich meinen Fehler suchen muss - ich komm nämlich einfach nicht weiter
\// Mogoon
-
du brauchst einen debugger wie gdb. dann kannst du ganz allein rausfinden, wo deine fehler sind.
-
OK. Mal angenommen, ich habe den gdb richtig bedient...
...dann sagt der mir folgendes:78 while (test=(a <= telaus)) /*Bodenreaktion (vertikal)*/
(gdb) step
97 plocal->FzB=f;
(gdb) print test
$2 = 0
(gdb) print a
$3 = 1.5728609397291513
(gdb) print telaus
$4 = 1.5880365163804104
(gdb)Das erscheint mir nicht ganz logisch...
-
kannst du den effekt (in einem kleineren programm) reproduzieren?
-
tja, hab den Fehler reproduzieren könnnen und dadurch letztendlich auch beheben. Mal wieder vor lauter Bäumen den Wald nicht gesehen:
Der Funktionsprototyp von int_eul_expl() gibt int zurück, die Funktion selbst (die ja in einer separaten Datei steht) aber double. Nachdem ich das geändert habe, läuft alles wunderbar.Jetzt würde mich ja fast noch interessieren, wo der Rückgabewert einer Funktion landet, wenn er nicht gebraucht wird und wie er von dort aus den Vergleich beeinflussen kann? Aber das nur nebenbei. Jedenfalls ist das Problem gelöst. Vielen Dank für den Tipp mit dem reproduzieren!
\// Mogoon
-
der rueckgabewert wird dann einfach nicht verwendet und kann eigentlich nichts beeinflussen. die funktion selber kann aber nebeneffekte haben.