Das folgende C++ Programm basiert auf dem Programm Lagrange_Polynom_1.cpp. Der Kern-Algorithmus des Programms wurde jedoch in eine Funktion "void Lagrange_Poly( ... )" ausgelagert.
// Musterlösung der Aufgabe 1 des Übungsblattes Nr.5 /* Die Berechnung des Lagrange Polynoms wurde in die * Funktion Lagrange_Poly( ... ) ausgelagert */ #include <iostream> // Ein- und Ausgabebibliothek double f(double x){ // Deklaration und Definition der Funktion f(x) die approximiert werden soll double wert; wert = 1.0/x; // Eigentliche Definition der Funktion return wert; // Rueckgabewert der Funktion f(x) } // Ende der Funktion f(x) void Lagrange_Poly(double* points, int N_points, double a, double b, const unsigned int N_xp, double* xp, double* fp, double* Pfp){ double dx = (b - a)/N_xp; // Abstand dx zwischen den aequidistanten Punkten des x-Intervalls double x = a - dx; // Aktueller x-Wert double Lk; // Deklaration einer Variable, die fuer Zwischenrechnungen benoetigt wird for(int j = 0; j <= N_xp; ++j){ // For-Schleife die ueber die einzelnen Punkte des x-Intervalls geht x=x+dx; // Aktueller x-Wert xp[j]=x; // Eintrag des aktuellen x-Wertes in das x-Array fp[j]=f(x); // Eintrag des aktuellen f(x)-Wertes in das f(x)-Array Pfp[j]=0; // Initialisierung des j-ten Polynom-Arrays mit 0 (Wert beim Anfang der Summenbildung) for(int k = 0; k < N_points; ++k){ // For-Schleife der Summation in der Lagrange Polynom Methode Lk=1; // Initialisierung der Produktvariable Lk mit 1 for(int i = 0; i < N_points; ++i){ // For-Schleife der Produktbildung in der Lagrange Polynom Methode if(i != k){ // Die Produktbildung soll nur fuer (i ungleich k) erfolgen Lk = Lk * (x - points[i])/(points[k] - points[i]); // Berechnung der Lk-Werte in der Lagrange Polynom Methode } // Ende if-Bedingung } // Ende for-Schleife der Produktbildung Pfp[j] = Pfp[j] + f(points[k])*Lk; // Kern-Gleichung in der Lagrange Polynom Methode } // Ende for-Schleife der Summenbildung } // Ende der for-Schleife ueber die einzelnen Punkte des x-Intervalls } // Ende der Funktion f(x) int main(){ // Hauptfunktion double points[] = { 2, 2.5, 4 }; // Deklaration und Initialisierung der Stützstellen als double-Array const unsigned int N_points = sizeof(points)/sizeof(points[0]); // Anzahl der Punkte die zur Approximation verwendet werden double plot_a=0.5; // Untergrenze des x-Intervalls in dem die Ergebnisse ausgegeben werden sollen double plot_b=6; // Obergrenze des x-Intervalls in dem die Ergebnisse ausgegeben werden sollen const unsigned int N_xp=300; // Anzahl der Punkte in die das x-Intervall aufgeteilt wird double xp[N_xp+1]; // Deklaration der x-Ausgabe-Punkte als double-Array double fp[N_xp+1]; // Deklaration der f(x)-Ausgabe-Punkte als double-Array double Pfp[N_xp+1]; // Deklaration der Ausgabe-Punkte des approximierten Polynoms als double-Array printf("# x-Werte der %3d Stuetzstellen-Punkte: \n", N_points); // Beschreibung der ausgegebenen Groessen for(int k = 0; k < N_points; ++k){ // For-Schleife der Ausgabe der Stuetzstellen x-Werte printf("%10.5f",points[k]); // Ausgabe der Stuetzpunkte } // Ende for-Schleife der Ausgabe printf("\n"); // Zeilenumbruch printf("# 0: Index j \n# 1: x-Wert \n# 2: f(x)-Wert \n"); // Beschreibung der ausgegebenen Groessen printf("# 3: Approximierter Wert des Lagrange Polynoms P(x) \n"); // Beschreibung der ausgegebenen Groessen printf("# 4: Fehler zum wirklichen Wert f(x)-P(x) \n"); // Beschreibung der ausgegebenen Groessen Lagrange_Poly(points,N_points,plot_a,plot_b,N_xp,xp,fp,Pfp); // Berechnung der Wertetabelle des Lagrange Polynoms for(int j = 0; j <= N_xp; ++j){ // For-Schleife der separaten Ausgabe der berechneten Werte printf("%3d %14.10f %14.10f %14.10f %14.10f \n",j, xp[j], fp[j], Pfp[j], (fp[j] - Pfp[j])); // Ausgabe der berechneten Werte } // Ende for-Schleife der Ausgabe } // Ende der Hauptfunktion
Die ersten fünf Einträge in der Argumentenliste der Funktion werden bei ihrem Aufruf initialisiert und die darauf folgenden drei Argumente stellen die Zeiger auf die im Hauptprogramm deklarierten Arrays double xp[N_xp+1], double fp[N_xp+1] und double Pfp[N_xp+1] dar. Es wurde das Programm mit den Vorgaben ($f(x)=1/x$ und $\vec{x}=\left( 2, 2.5, 4 \right)$) getestet und das im Terminal ausgegebene Ergebnis entsprach exakt den zuvor berechneten Werten. Nun wurde das Lagrange Polynom vom Grade $n=8$ im Teilintervall $[a,b]=[0.91,9.07]$ mit $f(x) = 10 \, e^{-x/5} \cdot \hbox{sin}(3 \, x)$ und $\vec{x}=\left( 1,2,3,4,5,6,7,8,9 \right)$ berechnet (siehe A5_1a.cpp). Die nebenstehende Abbildung visualisiert die Ergebnisse des Programms (das zugehörige Python Skript findet man unter PythonPlot_A5_1.py).
Gegeben seien die folgenden x- und y-Werte der Stützstellen: $\vec{x} = \left( 2, 10.1, 15, 20, 40, 60, 90 \right)$ und $\vec{y} = \left( 2.1, 41, 43, 40.2, 12, 5, 17.5 \right)$. Das folgende C++ Programm berechnet das Lagrange Polynom $P_6(x)$ im Teilintervall $[a,b]=[0,100]$. Als Vorlage des Programms wurde bereits das in der vorigen Aufgabe vorgestellte Musterlösungsprogramm A5_1.cpp verwendet, bei welchem der Kern-Algorithmus der Lagrange Polynom Methode in eine Funktion ausgelagert wurde. Die wesentliche Abänderung wurde in der Kern-Gleichung der Lagrange Polynom Methode gemacht (Anweisung: "Pfp[j] = Pfp[j] + points_y[k]*Lk;") bei der nun nicht die "f(points[k])"-Werte, sondern die "points_y[k]"-Werte stehen.
// Musterlösung der Aufgabe 2 des Übungsblattes Nr.5 /* Die Berechnung des Lagrange Polynoms wurde in die * Funktion Lagrange_Poly( ... ) ausgelagert * es wurde keine Funktion f(x) definiert, sondern * zusätzlich zu den x-Werten der Stützstellen * wurden auch die y-Werte angegeben */ #include <iostream> // Ein- und Ausgabebibliothek void Lagrange_Poly(double* points, double* points_y, int N_points, double a, double b, const unsigned int N_xp, double* xp, double* Pfp){ double dx = (b - a)/N_xp; // Abstand dx zwischen den aequidistanten Punkten des x-Intervalls double x = a - dx; // Aktueller x-Wert double Lk; // Deklaration einer Variable, die fuer Zwischenrechnungen benoetigt wird for(int j = 0; j <= N_xp; ++j){ // For-Schleife die ueber die einzelnen Punkte des x-Intervalls geht x=x+dx; // Aktueller x-Wert xp[j]=x; // Eintrag des aktuellen x-Wertes in das x-Array Pfp[j]=0; // Initialisierung des j-ten Polynom-Arrays mit 0 (Wert beim Anfang der Summenbildung) for(int k = 0; k < N_points; ++k){ // For-Schleife der Summation in der Lagrange Polynom Methode Lk=1; // Initialisierung der Produktvariable Lk mit 1 for(int i = 0; i < N_points; ++i){ // For-Schleife der Produktbildung in der Lagrange Polynom Methode if(i != k){ // Die Produktbildung soll nur fuer (i ungleich k) erfolgen Lk = Lk * (x - points[i])/(points[k] - points[i]); // Berechnung der Lk-Werte in der Lagrange Polynom Methode } // Ende if-Bedingung } // Ende for-Schleife der Produktbildung Pfp[j] = Pfp[j] + points_y[k]*Lk; // Kern-Gleichung in der Lagrange Polynom Methode } // Ende for-Schleife der Summenbildung } // Ende der for-Schleife ueber die einzelnen Punkte des x-Intervalls } // Ende der Funktion Lagrange_Poly(...) int main(){ // Hauptfunktion double points[] = { 2, 10.1, 15, 20, 40, 60, 90 }; // Deklaration und Initialisierung der Stützstellen als double-Array double points_y[] = { 2.1, 41, 43, 40.2, 12, 5, 17.5 }; // Deklaration und Initialisierung der Stützstellen als double-Array const unsigned int N_points = sizeof(points)/sizeof(points[0]); // Anzahl der Punkte die zur Approximation verwendet werden double plot_a=1; // Untergrenze des x-Intervalls in dem die Ergebnisse ausgegeben werden sollen double plot_b=90.7; // Obergrenze des x-Intervalls in dem die Ergebnisse ausgegeben werden sollen const unsigned int N_xp=500; // Anzahl der Punkte in die das x-Intervall aufgeteilt wird double xp[N_xp+1]; // Deklaration der x-Ausgabe-Punkte als double-Array double Pfp[N_xp+1]; // Deklaration der Ausgabe-Punkte des approximierten Polynoms als double-Array printf("# x-Werte der %3d Stuetzstellen-Punkte: \n", N_points); // Beschreibung der ausgegebenen Groessen for(int k = 0; k < N_points; ++k){ // For-Schleife der Ausgabe der Stuetzstellen x-Werte printf("%10.5f",points[k]); // Ausgabe der Stuetzpunkte } // Ende for-Schleife der Ausgabe printf("\n"); // Zeilenumbruch printf("# y-Werte der %3d Stuetzstellen-Punkte: \n", N_points); // Beschreibung der ausgegebenen Groessen for(int k = 0; k < N_points; ++k){ // For-Schleife der Ausgabe der Stuetzstellen y-Werte printf("%10.5f",points_y[k]); // Ausgabe der Stuetzpunkte } // Ende for-Schleife der Ausgabe printf("\n"); // Zeilenumbruch printf("# 0: Index j \n# 1: x-Wert \n"); // Beschreibung der ausgegebenen Groessen printf("# 2: Approximierter Wert des Lagrange Polynoms P(x) \n"); // Beschreibung der ausgegebenen Groessen Lagrange_Poly(points,points_y,N_points,plot_a,plot_b,N_xp,xp,Pfp); // Berechnung der Wertetabelle des Lagrange Polynoms for(int j = 0; j <= N_xp; ++j){ // For-Schleife der separaten Ausgabe der berechneten Werte printf("%3d %14.10f %14.10f \n",j, xp[j], Pfp[j]); // Ausgabe der berechneten Werte } // Ende for-Schleife der Ausgabe } // Ende der Hauptfunktion
Die nebenstehende Abbildung visualisiert die Ergebnisse des Programms (das zugehörige Python Skript findet man unter PythonPlot_A5_2.py).
Im unten dargestellten C++ Programm wurde zwei Tausch-Funktionen definiert, wobei nur eine von diesen eine wirkliche Vertauschung der Zahlenwerte von a und b realisiert. Die Terminalausgabe des Programms ist in der oberen rechten Abbildung zu sehen. Die Funktion "void Tausche_ab_FALSCH(double a, double b){ ... }" ist ein FALSCHER Versuch einer Tauschfunktion! Die Funktion benutzt in der Argumentenliste direkt die double-Variablen double a und double b. Der Gültigkeitsbereich dieser lokalen Variablen ist jedoch lediglich auf den 'Block von Anweisungen' der Funktion beschränkt und kann deshalb die Werte der Variablen a und b der main()-Funktion nicht verändern bzw. austauschen. Die Funktion "void Tausche_ab(double* pa, double* pb){ ... }" benutzt hingegen die Zeiger auf a und auf b in der Argumentenliste und kann somit auf die Werte vertauschen. Im Programm wurde zunächst die ursprünglichen initialisierten Werte der Variablen a und b ausgegeben, danach die falsche Tauschfunktion aufgerufen und erneut die aktuellen Werte von a und b im Terminal ausgegeben. Dann wurde die "richtige" Tauschfunktion ausgeführt und erneut der Wert der Variablen ausgegeben.
// Musterlösung der Aufgabe 3 des Übungsblattes Nr.5 #include <iostream> // Ein- und Ausgabebibliothek // Tauschfunktion mit Argumentenliste von Zeigern auf a und b void Tausche_ab(double* pa, double* pb){ printf("Vertausche a mit b \n"); double tmp = *(pa); // Speichert den Wert von a *(pa) = *(pb); // Schreibt den Wert von b in a *(pb) = tmp; // Schreibt den alten Wert von a in b } // Tauschfunktion mit Argumentenliste von double Variablen a und b // Problem: a und b sind lokale Variablen, die ihren Gueltigkeitsbereich // nur innerhalb des Anweisungsblockes der Funktion hat void Tausche_ab_FALSCH(double a, double b){ printf("Vertausche a mit b (aber FALSCH !) \n"); double tmp = a; // Speichert den Wert von a a = b; // Schreibt den Wert von b in a b = tmp; // Schreibt den alten Wert von a in b } int main(){ // Hauptfunktion double a = 5.437; // Definition a double b = 1.234; // Definition b printf("a = %6.3f , b = %6.3f \n", a,b); Tausche_ab_FALSCH(a,b); // führe falsche Tauschfunktion aus printf("a = %6.3f , b = %6.3f \n", a,b); Tausche_ab(&a,&b); // führe richtige Tauschfunktion aus printf("a = %6.3f , b = %6.3f \n", a,b); }