Numerische Integration(alle Regeln)



  • BeneSchw schrieb:

    die fkt nich rcihtig injetziert(?)

    sorry also er sagt implict declartion of function hat aber sonst noch nie was gemacht.



  • oben im header steht schon #include math.h

    Dann poste auch entsprechenden Code der der Realität entspricht.

    ich schätze das ändert nichts ob ich sei denn jetzt über die main schreibe oder nicht.

    Mit schätzen sollte man vorsichtig sein...

    Vergleiche mal:
    http://codepad.org/TQyCg6SN
    http://codepad.org/5jL8Vqv4



  • Also mit vorherigem deklariern gibt er jetzt komplett andere Werte aus und die Warnings sind weg aber das Probelm besteht immernoch dass er beim integral von 0 bis 2 von x^2 schon bei n=2 den exakten wert ausgibt, was aber nicht sein sollte. Die werte dannach werden immer ungenauer.

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #define m 100
    void numint(float a,float b);
    int main()
    {   float a;
        float b;
        printf("obere grenze eingeben:");
        scanf("%f",&a);
        printf("untere grenze eingeben:");
        scanf("%f",&b);
        numint(a,b);
    }
    
    void numint(float a,float b){
        int n[]= {1,2,3,4,5,6};
        float res[]={0,0,0,0,0,0};
        float h= ((b-a));
        int ns[] ={2,6,8,90,288,840};
        float fi;
        float help;
        int *zeiger;
        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/n[i];
        if(n[i]==1){
            zeiger =&oa[0];
        }if(n[i]==2){
            zeiger =&ob[0];
        }if(n[i]==3){
            zeiger =&oc[0];
        }if(n[i]==4){
            zeiger =&od[0];
        }if(n[i]==5){
            zeiger =&oe[0];
        }if(n[i]==6){
            zeiger =&of[0];
        }
        for(int j=0;j<n[i]+1;j++){
            help = *(zeiger+j);
            fi = a+j*h;
            //res[i]+=help*fi;
            res[i]+=help*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]*((a-b)/ns[i]);
    
    }
    for(int i=0;i<6;i++){
        printf("n=%i: %f\n",i+1, res[i]);
    }
    
    }
    

    Werte bei help*pow(fi,2):
    n=1 4.00 (stimmt)
    n=2 2.666667 (ab hier stimmt nichtmehr) ist der normale integralwert sollte bei n=4 kommen
    n=3 4.666667
    n=4 6.740741
    n=5 7.671296
    n=6 7.933519



  • Hier nochmal der WikipediaLink zur numerischen integration:
    https://de.wikipedia.org/wiki/Numerische_Integration


  • Mod

    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 verkapptes switch() , das Zeiger verbiegt. Das kann man sicherlich auch schöner machen.
    Und n[] 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 Du oa-of in ein Array quetschst.
    Problem ist natürlich, dass die einzelnen Zeilen verschiedene Längen haben. Wahrscheinlich hast Du sogar schon

    const 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 😃


  • Mod

    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 und ausgabe . 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.


Anmelden zum Antworten