Integration von Funktionen mit C

Und meine Methode ist noch viel zu langsam:

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
}

Was habe ich mir nur dabei gedacht? Viel zu viele Multiplikationen.

So gehts schneller:

Code:
float help;
[...]
summe=0.0;
help=x;
for (n=0;n<=Grad;n++)
{
summe+=Koeffizient[n]*help;
help*=help;
}

Im ersten Codeschnipsel wären es n² Multiplikationen, im zweiten leidiglich 2*n. Bei hohen Polynomgraden sind das schon ein paar Sekündchen Rechenzeit.

Was meinst Du mit der Differenz?

Integration in Grenzen bedeutet, die Fläche zwischen der Funktion und der Argument-Achse zu berechnen. Das mit einem Computer analytisch zu lösen ist ziemlich kompliziert, numerisch aber nicht. Du nimmst Dir einfach ein möglichst kleines Funktionsstück und berechnest die Fläche davon. Das wäre bei meiner Methode

Code:
s*(Funktionswert(x+s)+Funktionswert(x))/2;

s ist die Schrittweite, multipliziert mit dem geometrischen Mittelwert der beiden Stützstellen. Auf diese berechnete Fläche addiere ich alle weiteren kleinen Flächen, bis die obere Grenze erreicht ist.

Gruß
Morgoth
 
Bei dem Programm soll die Schrittweite immer weiter verkleinern und somit zu der gewünschten Genauigkeit zu kommen, die man zuvor eingegeben hat.

Wenn das Programm in die while-schleife gelang entstehen so wie ich es gemacht habe zwei werte. Die Differenz dieser beiden ist dann die Veränderung des Ergebnisses hinter dem Komma. Wenn die Veränderung noch nicht keiner z.B. 0.0001 beträgt wird sie schrittweite verkleinert.

Ich habe keine Ahnung wie ich es besser hätte machen sollen...

Hast du einen Vorschlag?

Danke
 
Ne, da fällt mir auch nichts besseres ein. Es gibt zwar Fehlerabschätzungen, aber dazu benötigt man die zweifache Ableitung, und die muss man ja wiederum numerisch errechnen.

Mir ist aber noch ne Idee gekommen, das ganze noch weiter zu beschleunigen:

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

2 Variablen mehr (fx und fxs), Programm eine Idee länger, aber dafür die Multiplikationen ungefähr auf die Hälfte reduziert.

Gruß
Morgoth
 
was mußt du eigentlich machen, die Metode implementieren, oder polynome integrieren?

den zweiteres ist ja eigentlich trivial :

du hast c*x hoch (n-1)

nun brauchst du nur ein a so dass a*n=c

habe es in 2 minuten aus Spaß hingeschrieben (du brauchst wahrscheinlich die andere methode, aber trotzdem )

Code:
float re,gr[2]={a,b};

for (int i=0;i<2;i++)
{
y[i]=0;
for (k=0; k<=n; k++)
p[k]=p[k]/(k+1);
y[i] += p[k]*pow(gr[i],k+1); //pow(basis,expo)
}

re=y[1]-y[0];
 
Zuletzt bearbeitet:
Vielen dank für die Hilfen...
Das Programm läuft jetzt zufriedenstellen, denke ich...


Gruß
SnuffNick
 
Hallo!

Ich wollte nur eben einen kleinen Teil des Programmes ändern:

Ich habe an der mit den ??? markierten Stelle aus s=s+2 -> s=s*2
gemacht.
Wenn ich jetzt bei einer Funktion 2 Grades mit allen Koeffizienten =2
und den grenzen u=1 und o=2 mit der Genauigkeit 0.0000001 bekomme ich eine Fehlermeldung "... "read" konnte nicht auf dem Speicher ausgeführt werden...

Woran liegt das...
Bei der Genauigkeit von 0.001 funktioniert das Programm...

Danke nochmals...

Gruß
SnuffNick


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

int main ()
{
int i, j, k, n, s;
/*  i: Laufvariable    		j: Laufvariable
    k: Laufvariable    		n: Grad des Polynoms
    s: Anzahl der Streifen  */
    
float diff, h, koffi[1000]={0}, o, summe_i, summe[3], u, x[1000], y[1000];

/*   diff: Gewünschte Genauigkeit des Ergebnisses
     h: Streifenbreite (Schrittweite)
     summe_i: Summer der inneren Stützwerte
     koffi[1000]: Feld für  Koeffizienten des Polynoms
   	 o: Ober Integrationsgrenze
   	 u: Untere Integrationsgrenze
  	 summe[2]: Feld für Zwischenergebnisse und Endergebnis
  	 x[1000]: Feld für  Stützstellen
  	 y[1000]: Feld für Stützwerte  */

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

// Den Grad des Polynoms einlesen
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);
    
// Einlesen der Koeffizienten
printf ("\n\n\nBitte geben Sie die Koeffizienten der Funktion y(x) ein:\n\n\n");

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

// Ausgabe der Funktion
printf ("\nDie zu integrierende Funktion lautet:");

printf ("\n\n\n\ty(x) = %5.2f", koffi[0]);
for (i=1; i<=n; i++)
    printf (" + %5.2f*x^%d",koffi[i],i);

// Einlesen der Integrationsgrenzen
printf ("\n\n\n\nBitte geben Sie ein:\n");
printf ("--------------------");
printf ("\n\nObere Integrationsgrenze: o = ");
scanf ("%f", &o);
printf ("\n\nUntere Integrationsgrenze: u = ");
scanf ("%f", &u);

// Erneute Eingabe der Grenzen bei gleichen Werten
while (o == u)
      {
      printf("\n\n\nDa die Grenzen gleich sind ergibt sich ein Integralwert von 0.\nBitte erneut eingeben.");
      printf ("\n\n\nObere Integrationsgrenze: o = ");
      scanf ("%f", &o);
      printf ("\n\nUntere Integrationsgrenze: u = ");
      scanf ("%f", &u);
      }

// Einlesen der gewünschten Genauigkeit des Ergebnisses
printf ("\n\n\nBitte geben Sie die gewuenschte Genauigkeit des Ergebnisses ein:\n\n");
printf ("Als Dezimalzahl (z.B. 0.001) : ");
scanf ("%f", &diff);

s=10; // Anzahl der Streifen (Startwert)

do   // Anfang der do-while-Schleife
{
      for (j=0; j<=1; j++)
      {
      summe[j]=0;

             for (i=0; i<=s; i++)
                 {
                 h=(o-u)/s;      // Berechnung der Streifenbreite
                 x[i]=0;
                 x[i]=u+(h*i);   // Berechnung der Stützstelle

                 y[i]=0;

                    for (k=0; k<=n; k++)   // Berechnung des Polynoms mit der Stützstelle
                        y[i] += koffi[k]*pow(x[i],k);        // pow(basis,expo)
             }

       summe_i=0;

                    for (i=1; i<s ; i++)   //  Berechnung der Summe der inneren Stützwerte
                        summe_i += y[i];

// Trapezformel	(y[0]+y[s]: Summe der äußeren Stützwerte)
       summe[j]=((y[0] + y[s])/2 + summe_i) * h;


??????????????????????????????????

       s=s*2; // Die Anzahl der Streifen wird verdoppelt

??????????????????????????????????

       }
// Differenz der Summen vom ersten zum zweiten Durchlauf
summe[2]=summe[0]-summe[1];

}
// do-while-Schleife: Wird durchlaufen bis gewuenschte Genauigkeit erreicht ist
while (summe[2] > diff || summe[2] < -diff);

// Ausgabe des Ergebnisses
printf ("\n\n\nZ = %20.10f\n\n\n\n",summe[1]);

    system("PAUSE");

}
 
Zurück
Oben