Integration von Funktionen mit C

snuffnick

Cadet 2nd Year
Registriert
Juli 2005
Beiträge
22
Hallo!

Ich schreibe ein Programm indem ich durch numerische Integration den Integralwert bestimmen möchte.
Die Funktionen sind vom Typ:

y(x) = a0 + a1*x + a2*x^2 + ... + an*x^n

In dem Programm frage ich zuerst die Werte für s,a,b ab, und gelange dann zu dieser For-Schleife.

Mein Problem ist nun, dass ich nur Funktionen bis zum Grad 3 berechnen kann. Weiß jemand wie ich das
anders machen kann, damit ich Funktionen höherer Ordnung auswerten kann? Mir ist klar das ich diese
Schleife erweitern kann, aber das ist meiner Meinung ja kein schöner weg.


n: Grad des Polynoms
s: Streifenbreite bei der Numerischen Integration
a,b: Grenzen des Integrals.


for (i=0; i<=s; i++)
{

h=(b-a)/s;
x=a+(h*i);

if (n==0)
y = p[0];

if (n==1)
y = p[0] + p[1]*x;

if (n==2)
y = p[0] + p[1]*x + p[2]*x*x;

if (n==3)
y = p[0] + p[1]*x + p[2]*x*x + p[3]*x*x*x;

}

Vielen Dank im voraus
Gruß
SnuffNick
 
Hi,

du könntest es folgendermaßen machen :

Code:
for (j=0;j<=n;j++)
{
y[i]+=p[j]*pow(x[i],j);
}
 
Könntest du vielleicht sagen, wie das Funktioniert...
Dieses habe ich noch nicht gesehen, denn ich programmiere noch nicht so lange..

Danke
 
du hast ja die ersten 3 aufgeschrieben, wenn du es dir anschaust erkennst du das Muster in der schleife:

z.b.

Code:
y[i]=p[0] für n=0

also würde es in der schleife so aussehen:

n=0
j=0
y[i]=p[j]*x[i] hoch j
y[i]=p[0]*1 da eine zahl hoch 0 gleich 1 ist


y[i] = p[0] + p[1]*x[i] für n=1

entsprechende schleife
n=1
j=0
y[i]=p[0]*1 nache dem ersten durchlauf

 dazu wird noch addiert :
j=1
p[1]*x[i] hoch 1 also 
p[1]*x[i] im zweiten durchlauf

usw.

rechne es am besten auf Papier aus, dann siehst du wie es funktioniert
 
Zuletzt bearbeitet:
Vielen dank!

Mir ist klar wie das funktioniert, aber ich habe eine fehlermeldung "... konnte nicht auf Speicher geschrieben werden"

Ich habe die Var alle als float eingelesen, bis auf j,n, usw.
Muß ich welche als double einlesen?
Ich habe das ausprobiet und die Werte für p sind dann alle 0.

Danke im voraus
 
du könntest das Programm posten (in code tags) , vielleicht finden wir so den Fehler
 
Hier das Programm. Sind noch ein paar sachen drinn, wegen n-max gleich drei...



Code:
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <math.h>

main ()

{
int i, j,k, n, s;
float a, b, h, m, p[500]={0}, summand2, summe1, summe2, summe[2]={0}, x[500]={0}, y[500]={0},;


printf ("\n\tNumerische Integartion mit Hilfe der Trapezregel!\n");
printf ("\t-------------------------------------------------\n\n");
printf ("\ty(x) = a0 + a1*x + a2*x^2 + ... + an*x^n\n");

printf ("\n\nBitte geben Sie den Grad n (max=3) des zu integrierenden Polynoms ein: n = ");
scanf ("%d", &n);
	
while (n > 3)
      {
      printf("\n\nDer Grad des Polynoms ist groesser als n-max = 3.\nBitte erneut eingeben.\n");
      printf ("\n\nBitte geben Sie den Grad n (max=3) des zu integrierenden Polynoms ein: n = ");
      scanf ("%d", &n);
      }

printf ("\n\n\ty(x) = a0");
for (i=1; i<=n; i++)
    {
    printf (" + a%d*x^%d",i,i); 
    }

printf ("\n\n\nBitte geben Sie die Koeffizienten der Funktion y(x) ein:\n\n\n");

printf ("a0 = ");
scanf ("%f", &p[0]);
printf ("\n");
for (i=1; i<=n; i++)
{
printf ("a%d = ",i);
scanf ("%f", &p[i]);
printf ("\n");
}

printf ("\nDie zu integrierende Funktion lautet:"); 
printf ("\n\n\n\ty(x) = %5.2f", p[0]);  

for (i=1; i<=n; i++)
    {
    printf (" + %5.2f*x^%d",p[i],i); 
    }
    

printf ("\n\n\n\nBitte geben Sie ein:");
printf ("\n--------------------");
printf ("\n\nOber Integrationsgrenze: b = ");
scanf ("%f", &b);
printf ("\n\nUnter Integrationsgrenze: a = ");
scanf ("%f", &a);

while (b == a)
      {
      printf("\n\n\nDa die Grenzen gleich sind ergibt ein Integralwert von 0.\nBitte erneut eingeben.");
      printf ("\n\n\nOber Integrationsgrenze: b = ");
      scanf ("%f", &b);
      printf ("\n\nUnter Integrationsgrenze: a = ");
      scanf ("%f", &a);
      }

printf ("\n\n\nBitte geben Sie die gewuenschte Genauigkeit des Ergebnises ein:\n\n"); 
printf ("Als Dezimalzahl (z.B. 0.001) : "); 
scanf ("%f", &m);

s=10;
summe[2]=m+1;

while (summe[2] > m || summe[2] < -m)
{
      
      for (j=0; j<=1; j++)
      {       
              
                      
             for (i=0; i<=s; i++)
             {
                 
             h=(b-a)/s;    
             x[i]=a+(h*i);
             
             for (k=0; k<=n; k++)
                 {
                 y[i] = y[i] + p[k]*pow(x[i],k); //pow(basis,expo)
                 }
             
             }
 
 
             summe1 = y[0] + y[s];           
             summand2=0;
             summe2=0; 

                    for (i=1; i<s ; i++)
                    {
                    summand2 = y[i];
                    summe2 += summand2;
                    }    

                         summe[j]=(summe1/2 + summe2) * h;

                         s+=5;

     }
       
summe[2]=summe[0]-summe[1];

}

printf ("\n\n\nZ = %20.10f\n\n",summe[1]);
printf ("\n\n");
    system("PAUSE");

}
 
Eiwei, was machst denn Du da mit den ganzen Arrays?

Alles unnötig.

Um den Funktionswert eines Polynoms beliebigen Grades auszurechnen benötigst Du:

- den Grad des Polynoms
- sämtliche Koeffizienten

Dann sieht das ungefähr so aus:

Code:
summe=0.0;
for (n=Grad;n>=0;n--)
{
summe+=Koeffizient[n]*x^n;  
//für x^n gibts auch irgendeine Funktion 
//oder selber schreiben, ist nur ne for-Schleife
}

Zack, am Ende steht der Funktionswert an der Stelle x.

Willst Du jetzt das Integral dieser Funktion zwischen zwei Grenzen berechnen, brauchst Du exakt 3 Variablen mehr: die untere Grenze (u), die obere Grenze (o), die Schrittweite (s).

Und dann einfach aufsummieren:

Code:
integral=0.0;
for (x=u; x<o; x+=s)
{
integral=integral+s*(Funktionswert(x+s)+Funktionswert(x))/2;
}

Fertig ist die Kiste. Da brauchts kein x[500] oder solche Scherze.

Die Akkumulation der Ergebnisvariable spart ne Menge Speicher und langsamer ist es auch nicht. Außerdem ist so der Grad des Polynoms auf unsigned int oder dem Speicher des Rechners, was immer als erstes kommt. Das ist eine ganze Menge mehr als Deine läppischen ;) 500.

Gruß
Morgoth
 
Danke, aber leider bin ich jetzt etwas durcheinander... Ich habe das programm etwas verändert und komm mit der Stelle x^n nicht klar...

Außerdem brauche ich aber doch die Arrays um die differenz zu bestimmen, oder?

Was meinst du mit unsigned int...
 
füge folgende Zeile vor der neuen Schleife ein:

y=0;

danach sollte deine Version gehen
 
unsigned int steht für vorzeichlose zahlen. auf einem 32bit system üblicher weise 0 bis 2^32-1 statt int was auch vorzeichen haben darf und so von -2^31 bis 2^31-1 geht, da der grad einer funktion positiv sein muss, kannst du also unsigned int statt int nehmen.
 
Ich habe am Anfang doch bei float y[500]={0}.
Reicht das denn nicht?

Ich bekomm es einfach nicht hin...

Danke
 
theoretisch sollte es reichen, ich bekomme aber damit ein segmentation fault.
Da ich kein Fehler erkennen konnte habe ich es so versucht->bei mir geht es, hast du es so probiert?
 
Ich habe es probiert, es scheint zu klappen...

Aber ich wollte mir die Einzelnen y werte anzeigen lassen, und da steht ganz viel komisches...

Ich post es noch mal...


Code:
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <math.h>

main ()

{
int i, j,k, n, s;
float a, b, h, m, p[500]={0}, summand2, summe1, summe2, summe[2]={0}, x[500]={0}, y[500]={0},;


printf ("\n\tNumerische Integartion mit Hilfe der Trapezregel!\n");
printf ("\t-------------------------------------------------\n\n");
printf ("\ty(x) = a0 + a1*x + a2*x^2 + ... + an*x^n\n");

printf ("\n\nBitte geben Sie den Grad n des zu integrierenden Polynoms ein: n = ");
scanf ("%d", &n);
	
printf ("\n\n\ty(x) = a0");
for (i=1; i<=n; i++)
    {
    printf (" + a%d*x^%d",i,i); 
    }

printf ("\n\n\nBitte geben Sie die Koeffizienten der Funktion y(x) ein:\n\n\n");

printf ("a0 = ");
scanf ("%f", &p[0]);
printf ("\n");
for (i=1; i<=n; i++)
{
printf ("a%d = ",i);
scanf ("%f", &p[i]);
printf ("\n");
}

printf ("\nDie zu integrierende Funktion lautet:"); 
printf ("\n\n\n\ty(x) = %5.2f", p[0]);  

for (i=1; i<=n; i++)
    {
    printf (" + %5.2f*x^%d",p[i],i); 
    }
    

printf ("\n\n\n\nBitte geben Sie ein:");
printf ("\n--------------------");
printf ("\n\nOber Integrationsgrenze: b = ");
scanf ("%f", &b);
printf ("\n\nUnter Integrationsgrenze: a = ");
scanf ("%f", &a);

while (b == a)
      {
      printf("\n\n\nDa die Grenzen gleich sind ergibt ein Integralwert von 0.\nBitte erneut eingeben.");
      printf ("\n\n\nOber Integrationsgrenze: b = ");
      scanf ("%f", &b);
      printf ("\n\nUnter Integrationsgrenze: a = ");
      scanf ("%f", &a);
      }

printf ("\n\n\nBitte geben Sie die gewuenschte Genauigkeit des Ergebnises ein:\n\n"); 
printf ("Als Dezimalzahl (z.B. 0.001) : "); 
scanf ("%f", &m);

s=10;
summe[2]=m+1;

while (summe[2] > m || summe[2] < -m)
{
      
      for (j=0; j<=1; j++)
      {       
              
                      
             for (i=0; i<=s; i++)
             {
                 
             h=(b-a)/s;    
             x[i]=a+(h*i);
             
             y[i]=0;
             for (k=0; k<=n; k++)
                 {
                 y[i] = y[i] + p[k]*pow(x[i],k); //pow(basis,expo)
                 printf ("\ny[%5.2f] = %5.2f\n\n",i,y[i]);
                 }
             
             }
 
 
             summe1 = y[0] + y[s];           
             summand2=0;
             summe2=0; 

                    for (i=1; i<s ; i++)
                    {
                    summand2 = y[i];
                    summe2 += summand2;
                    }    

                         summe[j]=(summe1/2 + summe2) * h;

                         s+=5;

     }
       
summe[2]=summe[0]-summe[1];

}

printf ("\n\n\nZ = %20.10f\n\n",summe[1]);
printf ("\n\n");
    system("PAUSE");

}

Vielen dank
Gruß
SnuffNick
 
du musst für alle 500 elemente ein zuweisung durchführen. was du getan hast:
ein zeiger (zeiger=feld=zeiger in c) auf ein feld mit einem element zeigen lassen und dann auf weitere elemente zu gegriffen.
also:
float y[500]={0}
ist identisch mit
float *y={0}
letzteres verbietet die c-syntax aber so weit ich.
wenn du dann auf
y[1] zugreifst, bist du in keinem legalen speicher mehr. seg-fault.

versuch mal deinen compiler auf strict oder pedantic oder so was zu stellen, dann müsste er auch rumnörgeln.
 
soweit ich weiß wird bei einer Initialisierung mit zu wenig elementen 0 für die restlichen angenommen. (das meinte ich mit theoretisch :))

wegen der Ausgabe versuche es so
std::cout<<y<<'\n';
scheint aber richtig zu sein , das Ergebnis stimmt (habe aber nur ein Beispiel nachgerechnet)
 
Scheint zu stimmen...

Meint Ihr denn ich kann das so lassen, ich kann nicht einschätzen ob das von der programmierung so alles inordnung ist...

Vielleicht könnt ihr da was zu sagen...

Das müsste doch so mit jedem c-compiler funktionieren...

Ich benuzte dev-c++

Das programm muss aber auch mit visual projekt.net laufen, was ich aber leider momentan nicht testen kann...
 
iat ja ein ziemlich einfaches Programm, sollte kein Problem sein das zu kompilieren (hat bei mir auf einem Linux Rechner mit minimalen Änderungen auch geklappt)

du könntest zwei funktionen einführen (z.B: getData(), integrate() ) die du dann im main aufrufst
 
Wenn ich wüsste wie, würde ich das gerne versuchen.
Kannst du mir sagen was ich dann zu tun habe...

Vielen dank für die mühen...
 
im Moment hast du zuviele globale Variabeln. Eigentlich brauchst du nur die die zum Polynom gehören (grad, koeffizienten...)
Wenn du jetzt eine Funktion (z.B. getData(int grad, float prec,.. )) hast die den ersten Teil deines Programms übernimmt, und diesen Variablen einen Wert gibt.

z.B.
void getData (int x, float y)
{
x=blalbla
y=blabla
}

getdata kann dann im main mit beliebigen Werten aufgerufen (getdata(a,b) die Sachen die du brauchst )

Nun nimmt z.B. (integrate ) diese Werte und macht die Berechnung. Hilfsvariablen etc. brauchen getData und main nicht zu sehen.

im main rufst du getData(...) und dann integrate() auf.

weiterer Vorteil, wenn du z.B. Morgoths Methode anwenden willst, musst du dich nur um integrate kümmern, der Rest bleibt gleich
 
Zuletzt bearbeitet:
Zurück
Oben