C Progr.: Integral Berechnung < C/C++ < Programmiersprachen < Praxis < Informatik < Vorhilfe
|
Aufgabe | Der Wert des bestimmten Integrals I = [mm] \integral_{a}^{b}{f(x) dx} [/mm] lässt sich mittels folgender Formel (Trapezregel)
näherungsweise berechnen:
I [mm] \approx I_{n} [/mm] = [mm] \bruch{h}{2} [/mm] ( [mm] f(x_{0}) [/mm] + [mm] 2f(x_{1}) [/mm] + ... + [mm] 2f(x_{n-1}) [/mm] + [mm] f(x_{n}) [/mm] ) mit h = (b-a)/2
,
wobei n vorgegeben ist und die Stützstellen xi bestimmt sind durch:
xi = a + ih für, i = 0, 1, . . . , n .
Schreiben Sie ein Programm, das folgende Teile enthält:
eine double-wertige Funktion f mit dem Argument x für den folgenden Funktionsausdruck
f(x) = 2p1 − x2 (x 2 R, −1 x 1) ,
eine double-wertige Funktion trapez mit den Argumenten a, b und n, die einen Näherungswert
In gemäß der oben angegebenen Formel berechnet,
ein Hauptprogramm, in dem zunächst die Integrationsgrenzen a und b, sowie die gewünschte
relative Genauigkeit e eingelesen werden; die Berechnung von In mit Hilfe der Funktion trapez
soll dann in folgender Form durchgeführt werden: Erhöhen Sie n ausgehend von n = 10 solange
um den Wert 10, bis für ein vorgegebenes > 0 gilt:
(|In−10 − In|)/|In| < e mit I0 = 0 oder n > 250
Berechnen Sie die Werte des Integrals auf dem Intervall [−1, 1] für = 10−1, 10−3. Ihre Ausgabe
sollte sich an der folgenden Formatierung orientieren:
Index n = ... Naeherung I n = ... |
Hier mein Ansatz:
#include <math.h>
#include <stdio.h>
double f(double x) /* -1 <= x <= 1 */
{
double ergebnis;
ergebnis = 2 * sqrt( 1 - pow(x,2) );
return ergebnis;
}
double trapez(double [mm] intgrenze_a, [/mm] double [mm] intgrenze_b, [/mm] double n)
{
if(n==0) return 0;
else
{
int i;
double h, ergebnis=0;
h = [mm] (intgrenze_b [/mm] - [mm] intgrenze_a) [/mm] / n;
for(i=0; i<=n; i++)
{
if(i>0 && i<n) ergebnis = ergebnis + [mm] 2*f(intgrenze_a [/mm] + i*h);
else ergebnis = ergebnis + [mm] f(intgrenze_a [/mm] + i*h);
}
ergebnis = ergebnis * (h/2);
return ergebnis;
}
}
int main(void)
{
double integral;
double [mm] intgrenze_a, intgrenze_b, genauigkeit_e, [/mm] n;
printf("Untere Integrationsgrenze eingeben: a=");
scanf("%f", [mm] &intgrenze_a);
[/mm]
printf("Obere Integrationsgrenze eingeben: b=");
scanf("%f", [mm] &intgrenze_b);
[/mm]
printf("Relative Genauigkeit eingeben: e=");
scanf("%f", [mm] &genauigkeit_e);
[/mm]
integral = [mm] genauigkeit_e [/mm] + 1;
for(n=10; integral >= [mm] genauigkeit_e [/mm] && n <= 250; n+=10)
{
integral = ( fabs ( [mm] trapez(intgrenze_a, intgrenze_b, [/mm] n-10) - [mm] trapez(intgrenze_a, intgrenze_b, [/mm] n) ) )
/ fabs( [mm] trapez(intgrenze_a, intgrenze_b, [/mm] n) );
printf("Index n = %4f Naeherung [mm] I_n [/mm] = %f", n, integral);
}
[mm] printf("\n\n");
[/mm]
return 0;
}
Wenn ich die Ausgabe richtig deute, kommt bei mir - Unendlich raus, die Berechnung stimmt also nicht. Wo liegt der, bzw liegen die Fehler im Programm?
Vielen Dank für eure Mühe!
|
|
|
|
Status: |
(Mitteilung) Reaktion unnötig | Datum: | 18:20 Mi 19.12.2007 | Autor: | matux |
$MATUXTEXT(ueberfaellige_frage)
|
|
|
|
|
Habe das Programm mittlerweile selbst geschrieben:
#include <math.h> /* Mathe Bibliothek */
#include <stdio.h>
double f(double x) /* Berechnung der Funktionswerte */
{
double ergebnis;
ergebnis = 2 * sqrt( 1 - x*x );
return ergebnis;
}
double trapez(double [mm] intgrenze_a, [/mm] double [mm] intgrenze_b, [/mm] double n, double h) /* Berechnung des Integrals */
{
if(n==0) return 0;
else
{
int i;
double ergebnis=0;
for(i=0; i<=n; i++)
{
if(i>0 && i<n) ergebnis = ergebnis + [mm] 2*f(intgrenze_a [/mm] + i*h);
else ergebnis = ergebnis + [mm] f(intgrenze_a [/mm] + i*h);
}
ergebnis = ergebnis * (h/2);
return ergebnis;
}
}
int main(void)
{
double integral, h, ergebnis;
double [mm] intgrenze_a, intgrenze_b, genauigkeit_e, [/mm] n;
printf("Untere Integrationsgrenze eingeben: a=");
scanf("%lf", [mm] &intgrenze_a);
[/mm]
printf("Obere Integrationsgrenze eingeben: b=");
scanf("%lf", [mm] &intgrenze_b);
[/mm]
printf("Relative Genauigkeit eingeben: e=");
scanf("%lf", [mm] &genauigkeit_e);
[/mm]
integral = [mm] genauigkeit_e [/mm] + 1;
for(n=10; integral >= [mm] genauigkeit_e [/mm] && n <= 250; n+=10) /* Schleife zum Annaehern des Ergebnisses */
{
h = [mm] (intgrenze_b [/mm] - [mm] intgrenze_a) [/mm] / n;
ergebnis = [mm] trapez(intgrenze_a, intgrenze_b, [/mm] n, h);
printf("Index n = %4.0f Naeherung [mm] I_n [/mm] = %f \ n", n, ergebnis);
integral = ( fabs ( [mm] trapez(intgrenze_a, intgrenze_b, [/mm] n-10, h) - ergebnis ) )
/ fabs( [mm] trapez(intgrenze_a, intgrenze_b, [/mm] n, h) );
}
printf(" \ n \ n ");
return 0;
}
Es funktioniert bei mir zu Hause (Windows) auch einwandfrei. Aber auf dem Uni-Rechnern (Linux) passiert nicht dasselbe.
Bei mir läuft er für große Genauigkeit (z.B. e=0.0001) bis n=250 und gibt einen Wert aus, der schon sehr nah an [mm] \pi [/mm] liegt.
In der Uni bricht es bereits nach n=150 ab und der letzte Wert ist nan (=not a number) und die Werte vorher sind natürlich noch nicht so nah an [mm] \pi. [/mm] Wo ist der Fehler im Programm?
btw, Gibt es Möglichkeit den Mathecode im Beitrag zu deaktivieren?
|
|
|
|
|
Hallo Auron2009,
> Es funktioniert bei mir zu Hause (Windows) auch
> einwandfrei.
Ok, ich gehe jetzt einfach mal davon aus, daß es im Prinzip richtig programmiert ist.
Versuche dem Compiler alle Zahlen, die zu double-Wert-Ergebnissen beitragen, explizit mitzuteilen. Also z.B. statt ergebnis*h/2 schreibst du ergebnis*h/2.0.
Mache das bei allen Werten, wo es nötig ist.
Außerdem hast du bei der Funktion trapez() double ergebnis = 0; stehen, obwohl du C verwendest. Manche Compiler mögen das nicht. Also schreibe lieber double ergebnis; ergebnis = 0.0;
Hilft das immer noch nicht, würde ich nach jeder verdächtig erscheinenden Anweisung wie h/2 eine printf Ausgabe machen, um den Fehler einzugrenzen.
Grüße
Karl
|
|
|
|