Numerische Integration(alle Regeln)
-
Hier nochmal der WikipediaLink zur numerischen integration:
https://de.wikipedia.org/wiki/Numerische_Integration
-
Zeile 33. Welchen Wert hat h beim 3. Durchlauf vorher und nachher?
-
Oh jetzt wo du mich drauf aufmerksam machst. Evtl sollte ich h vor jedem durchlauf einfach mal auf 0 setzen sonst addieren sich die Werte ja, was ja nicht sein soll.
-
Der Großteil der
numint()
Funktion ist ein verkapptesswitch()
, das Zeiger verbiegt. Das kann man sicherlich auch schöner machen.
Undn[]
ist ja wohl Quark...ein Array, dass von 1 bis 6 zählt...:(//https://oeis.org/A100642 const int *cotesian(size_t row) { //assert(row<10); static const int data[] = { 0,1,1,1,4,1,1,3,3,1,7,32,12,32,7,19,75,50,50,75, 19,41,216,27,272,27,216,41,751,3577,1323,2989, 2989,1323,3577,751,989,5888,-928,10496,-4540, 10496,-928,5888,989,2857,15741,1080,19344,5778, 5778,19344,1080,15741,2857,16067}; return data+row*(row+1)/2; } //dann (ungetestet) for(int j=0;j<i+2;j++){ help = cotesian(i+1)[j]; fi = a+j*h; res[i]+=help*fi*fi; }
-
Also ich hab jetzt alles ein bisschen umgeschrieben...der compiler meckert nicht nichtmal warnings aber in Zeile 57, also sobald er mir das erste Ergebnis berechnet stürzt alles ab...
#include <stdio.h> #include <stdlib.h> #include <math.h> #define m 100 void numint(double a,double b); void berechnen(double h,int arr[],int l,int ns,int i); int main() { double a =2; double b=0; /* printf("obere grenze eingeben:"); scanf("%u",&a); printf("untere grenze eingeben:"); scanf("%u",&b);*/ numint(a,b); } void numint(double a,double b){ double h= ((a-b)); double ns[]={2,6,8,90,288,840}; int oa[] = {1,1}; int ob[] = {1,4,1}; int oc[] = {1,3,3,1}; int od[] = {7,32,12,32,7}; int oe[] = {19,75,50,50,75,19}; int of[] = {41,216,27,272,27,216,41}; for(int i=0;i<6;i++){ h = h/(i+1); switch(i){ case 0: berechnen(h,oa,2,ns[i],i); case 1: berechnen(h,ob,3,ns[i],i); case 2: berechnen(h,oc,4,ns[i],i); case 3: berechnen(h,od,5,ns[i],i); case 4: berechnen(h,oe,6,ns[i],i); case 5: berechnen(h,of,7,ns[i],i); } }} void berechnen(double h,int arr[],int l,int ns,int i){ double res[]={0,0,0,0,0,0}; double fi; for(int j=0;j<l+1;j++){ fi = j*h; //res[i]+=help*fi; res[i]+=arr[j]*pow(fi,2); //res[i]+= help*(1/(fi+1)); //res[i]+= help*sqrt(1+pow(fi,2)); //res[i]+= help*sin(fi); //res[i]+= help*exp(fi); //res[i]+= help*pow(fi,fi); } res[i] = res[i]*(2/ns); printf("n=%i: %f\n",i+1,res[i]); }
-
So ok hat sich von selbst gelöst ich denke dass das jetzt passt hab z.B. oben des break in der switch vergessen
Für alle dies interssiert jetziger Code :#include <stdio.h> #include <stdlib.h> #include <math.h> #define m 100 void numint(double a,double b); void berechnen(double h,int arr[],int l,double ns,int i); int main() { double a =2; double b=0; printf("obere grenze eingeben:"); scanf("%d",&a); printf("untere grenze eingeben:"); scanf("%d",&b); numint(a,b); } void numint(double a,double b){ double h=0; double ns[]={2,6,8,90,288,840}; int oa[] = {1,1}; int ob[] = {1,4,1}; int oc[] = {1,3,3,1}; int od[] = {7,32,12,32,7}; int oe[] = {19,75,50,50,75,19}; int of[] = {41,216,27,272,27,216,41}; for(int i=0;i<6;i++){ h = a/(i+1); switch(i){ case 0: berechnen(h,oa,2,ns[i],i);break; case 1: berechnen(h,ob,3,ns[i],i);break; case 2: berechnen(h,oc,4,ns[i],i);break; case 3: berechnen(h,od,5,ns[i],i);break; case 4: berechnen(h,oe,6,ns[i],i);break; case 5: berechnen(h,of,7,ns[i],i);break; } } } void berechnen(double h,int arr[],int l,double ns,int i){ double res=0; double fi=0; for(int j=0;j<l;j++){ fi = j*h; //res+=arr[j]*fi; //res+=arr[j]*pow(fi,2); //res+= arr[j]*(1/(fi+1)); //res+= arr[j]*sqrt(1+pow(fi,2)); //res+= arr[j]*sin(fi); res+= arr[j]*exp(fi); //res+= arr[j]*pow(fi,fi); } res = res*(2/ns); printf("n=%i: %f\n",i+1,res); }
Danke für die vielen Hilfeversuche und Verbesserungen! Ich hoffe ich lerne aus meinen Fehlern!
-
Nochmal eine andere Idee, die evtl. weniger "esoterisch" erscheint, als mein Ansatz von oben:
Du könntest das
switch-case
auch komplett einsparen, wenn Duoa-of
in ein Array quetschst.
Problem ist natürlich, dass die einzelnen Zeilen verschiedene Längen haben. Wahrscheinlich hast Du sogar schonconst int o[][] = { ... };
versucht hast und der Compiler beschied Dir, dass er alle Dimensionen eines Array bis auf die letzte braucht.
Da Du die Anzahl der Elemente der einzelnen Zeilen aber kennst, sehe ich kein Problem darin einfach jede Zeile mit der maximalen Länge - also 7 - zu deklarieren.
const int o[][7]= { {1,1}, {1,4,1}, {1,3,3,1}, ... };
Damit schnurren im folgenden die Zeilen 30-37 auf eine einzige zusammen.
-
Das ist jett erstmal zweitrangig
aber danke !:)
Mein Problem jetzt ist, dass ich eigentlich alles gleich gelassen ahb nur den Rückgabetyp verändert habe um die Fkt numintm() besser implementieren zu können und doch kommen völlig absude ergebnisse raus woran liegts?#include <stdio.h> #include <stdlib.h> #include <math.h> #define m 100 double ns[]={2,6,8,90,288,840}; int oa[] = {1,1}; int ob[] = {1,4,1}; int oc[] = {1,3,3,1}; int od[] = {7,32,12,32,7}; int oe[] = {19,75,50,50,75,19}; int of[] = {41,216,27,272,27,216,41}; double *ptr; double numintm(double a,double b,int n); double numint(double a,double b,int n); double berechnen(double h,int arr[],int l,double ns,double a,double b); int main() { double a =2; double b=0; int n=0; printf("obere grenze eingeben:\n"); scanf("%lf",&a); printf("untere grenze eingeben:\n"); scanf("%lf",&b); printf("n Wert eingeben:\n"); scanf("%i",&n); double res=numint(a,b,n); printf("\nWert bei n=%i: %f",n,res); } double numint(double a,double b,int i){ double h=0; h = (a-b)/(i); switch(i){ case 1: return berechnen(h,oa,2,ns[i-1],a,b);break; case 2: return berechnen(h,ob,3,ns[i-1],a,b);break; case 3: return berechnen(h,oc,4,ns[i-1],a,b);break; case 4: return berechnen(h,od,5,ns[i-1],a,b);break; case 5: return berechnen(h,oe,6,ns[i-1],a,b);break; case 6: return berechnen(h,of,7,ns[i-1],a,b);break; } } double numintm(double a,double b,int n){ double c=a/100; a=a/100; double res; for(int i=0;i<100;i++){ res+= numint(a,b,n); a+=c; b+=c; } return res; } double berechnen(double h,int* arr,int l,double ns,double a,double b){ double res=0; double fi=0; for(int j=0;j<l;j++){ fi = a+j*h; //res+=arr[j]*fi; res+=arr[j]*pow(fi,2); //res+= arr[j]*(1/(fi+1)); //res+= arr[j]*sqrt(1+pow(fi,2)); //res+= arr[j]*sin(fi); //res+= arr[j]*exp(fi); //res+= arr[j]*pow(fi,fi); } res = res*((a-b)/ns); return res; }
-
Du hast jetzt noch a und b mit in den Berechnungen drin.
-
Hallo DirkB das sollte aber nichts amchen, es ist nur die genauere beschreibung der formel. insofern ich mich irre,weil wenn ich anstatt a/(i+1) mit i =0,1,.. oder (a-b)/i mit i=1,2,3,...
schreibe sich nicht viel ändern sollte genauso bei (2/ns) ein (a-b)/ns, es ist alles nur verallegmeinert, sodass ich nicht nur 2 und 0 nehmen kann sondern auch die kleineren werte, wie sie bei numintm verlangt werden.
-
Okay hat sich geklärt hatte bei fi nen kleinen Fehler da kiommt anstatt a n b rein, also die untere und nicht die obere Grenze außerdem hab ich noch eine Ausgabe hinzugefügt:
#include <stdio.h> #include <stdlib.h> #include <math.h> #define m 100 double ns[]={2,6,8,90,288,840}; int oa[] = {1,1}; int ob[] = {1,4,1}; int oc[] = {1,3,3,1}; int od[] = {7,32,12,32,7}; int oe[] = {19,75,50,50,75,19}; int of[] = {41,216,27,272,27,216,41}; double numintm(double a,double b,int n,int fkt); double numint(double a,double b,int n,int fkt); double berechnen(double h,int arr[],int l,double ns,double a,double b,int fkt); void ausgabe(double a,double b); int main() { double a =2; double b=0; printf("obere grenze eingeben: "); scanf("%lf",&a); printf("untere grenze eingeben: "); scanf("%lf",&b); ausgabe(a,b); } double numint(double a,double b,int i,int fkt){ double h=0; h = (a-b)/(i); switch(i){ case 1: return berechnen(h,oa,2,ns[i-1],a,b,fkt);break; case 2: return berechnen(h,ob,3,ns[i-1],a,b,fkt);break; case 3: return berechnen(h,oc,4,ns[i-1],a,b,fkt);break; case 4: return berechnen(h,od,5,ns[i-1],a,b,fkt);break; case 5: return berechnen(h,oe,6,ns[i-1],a,b,fkt);break; case 6: return berechnen(h,of,7,ns[i-1],a,b,fkt);break; } } double numintm(double a,double b,int n,int fkt){ double c=a/100; a=a/100; double res; for(int i=0;i<100;i++){ res+= numint(a,b,n,fkt); a+=c; b+=c; } return res; } double berechnen(double h,int arr[],int l,double ns,double a,double b,int fkt){ double res=0; double fi=0; for(int j=0;j<l;j++){ fi = b+j*h; switch(fkt){ case 1:res+=arr[j]*1;break; case 2:res+=arr[j]*pow(fi,2);break; case 3:res+=arr[j]*pow(fi,4);break; case 4:res+= arr[j]*(1/(fi+1));break; case 5:res+= arr[j]*sqrt(1+pow(fi,2));break; case 6:res+= arr[j]*sin(fi);break; case 7:res+= arr[j]*exp(fi);break; case 8:res+= arr[j]*pow(fi,fi);break; } } res = res*((a-b)/ns); return res; } void ausgabe(double a, double b){ double res[6]={0}; printf("\nf(x) ||| n=1 || n=2 || n=3 || n=4 || n=5 || n=6 "); printf("\n_____________________________________________________________________________"); printf("\n1 |"); for(int i=0;i<6;i++){ res[i]=numint(a,b,i+1,1); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nx^2 |"); for(int i=0;i<6;i++){ res[i]=numint(a,b,i+1,2); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nx^4 "); for(int i=0;i<6;i++){ res[i]=numint(a,b,i+1,3); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\n1/x+1 |"); for(int i=0;i<6;i++){ res[i]=numint(a,b,i+1,4); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nsqrt(1+x^2) |"); for(int i=0;i<6;i++){ res[i]=numint(a,b,i+1,5); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nsin(x) |"); for(int i=0;i<6;i++){ res[i]=numint(a,b,i+1,6); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\ne^x |"); for(int i=0;i<6;i++){ res[i]=numint(a,b,i+1,7); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nx^x |"); for(int i=0;i<6;i++){ res[i]=numint(a,b,i+1,8); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________\n"); /** AB HIER UNTERTEILUNG IN INTERVALLE*/ printf("\nUnterteilung der Grenzen in 100 Intervalle\n"); printf("\nf(x) ||| n=1 || n=2 || n=3 || n=4 || n=5 || n=6 "); printf("\n_____________________________________________________________________________"); printf("\n1 |"); for(int i=0;i<6;i++){ res[i]=numintm(a,b,i+1,1); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nx^2 |"); for(int i=0;i<6;i++){ res[i]=numintm(a,b,i+1,2); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nx^4 |"); for(int i=0;i<6;i++){ res[i]=numintm(a,b,i+1,3); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\n1/x+1 |"); for(int i=0;i<6;i++){ res[i]=numintm(a,b,i+1,4); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nsqrt(1+x^2) |"); for(int i=0;i<6;i++){ res[i]=numintm(a,b,i+1,5); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nsin(x) |"); for(int i=0;i<6;i++){ res[i]=numintm(a,b,i+1,6); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\ne^x |"); for(int i=0;i<6;i++){ res[i]=numintm(a,b,i+1,7); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); printf("\nx^x |"); for(int i=0;i<6;i++){ res[i]=numintm(a,b,i+1,8); printf("||%f",res[i]); } printf("\n_____________________________________________________________________________"); }
Keine Ahnung ob die Irgendwie leichter ging aber war ja eh nur Copy+paste arbeit
-
Wenn man viel mit Copy&Paste programmiert, ist das fast immer schlecht. Das zeigt, dass man sein Problem nicht hinreichend abstrahiert hat.
Jetzt, wo du deine Hausaufgaben gelöst hast, kann ich auch vormachen, wie es besser ginge: Eine Funktion sollte genau eine Sache tun und diese gut. Der Name der Funktion sollte möglichst genau ausdrücken, was sie tut. Besonders schlecht in deinem Programm ist die Funktion
berechnen
undausgabe
. Die Namen drücken nicht aus, was passiert.ausgabe
berechnet etwas. berechnen versucht auf der einen Seite eine allgemeine Integrationsfunktion zu sein, ist aber andererseits merkwürdig beschränkt in der Auswahl der möglichen integrablen Funktionen, da diese fest im Code stehen.Und globale Variablen gehen mal überhaupt nicht. Todsünde.
Ein kurzes Beispiel, wie es besser ginge:
#include <assert.h> // Approximates the integral of the function f from a to b to the order of n. // The valid range for n is 1 to 6. double integrate(double (*f)(double), double a, double b, int n) { static const double coefficients[6][7]={ {1./2, 1./2}, {1./6, 4./6, 1./6}, {1./8, 3./8, 3./8, 1./8}, {7./90, 32./90, 12./90, 32./90, 7./90}, {19./288, 75./288, 50./288, 50./288, 75./288, 19./288}, {41./840, 216./840,27./840, 272./840, 27./840, 216./840, 41./840}}; double step = (b-a)/n; double sum = 0; assert(n > 0 && n < 7); for (int i = 0; i <= n; ++i) sum += f(a + i * step) * coefficients[n-1][i]; return sum * (b-a); } #include <stdio.h> #include <math.h> double xtox(double x) { return pow(x,x); } int main() { for (int i = 1; i <=6; ++i) printf("%d: %f\n", i, integrate(xtox, 4, 7, i)); }
PS: Hier vermisse ich C++
. Funktionsobjekte und Lambdaausdrücke sind doch was Schönes.