Die Berechnung des Schnittpunktes der Funktion $g(x)=x^3$ mit der Funktion $h(x)=$ln$(x)+5$ ist gleichbedeutend mit der Nullstellensuche der Funktion $f(x) := h(x) - g(x) = $ ln$(x) + 5 - x^3$. Das folgende C++ Programm stellt eine Musterlösung zur Aufgabe 1 dar:
// Musterlösung der Aufgabe 1 des Übungsblattes Nr.4 /* Methode der Bisektion (Intervallhalbierungsverfahren) * Berechnung des Schnittpunktes der Funktionen g(x)=x^3 und h(x)=ln(x)+5 im Intervall [0.25,2.5] * entspricht einer Nullstellensuche der Funktion f(x)=ln(x)+5-x^3 * Ausgabe zum Plotten (Gnuplot oder Python) mittels: "./a.out > A4_1.dat" */ #include <iostream> // Ein- und Ausgabebibliothek #include <cmath> // Bibliothek für mathematisches (e-Funktion, Betrag, ...) double f (double x) { // Deklaration und Definition der Funktion f(x) double wert; // Lokale double-Variable (nur im Bereich der Funktion gültig) wert = log(x) + 5 - pow(x,3); // Eigentliche Definition der Funktion return wert; // Rueckgabewert der Funktion f(x) } // Ende der Funktion f(x) int main(){ // Hauptfunktion int i; // Deklaration des Laufindex als ganze Zahl double a = 0.25; // Untergrenze des Intervalls [a,b] in dem f(x)=0 gelten soll double b = 2.5; // Obergrenze des Intervalls [a,b] in dem f(x)=0 gelten soll const int N = 10; // Anzahl der Iterationen im Intervallhalbierungsverfahren double p, fp; // Deklaration der Variablen des approximierten x- und f(x)-Wertes der Nullstelle double fa=f(a); // Deklaration und Initialisierung des Funktionswertes f(a) an der Untergrenze const double Loes = 1.7729093296693715; // Wirklicher Wert des Schnittpunktes printf("# 0: Index i der Iteration \n# 1: Approximierter Wert der Nullstelle p_i \n"); // Beschreibung der ausgegebenen Groessen printf("# 2: Funktionswert f(p_i) \n# 3: Relativer Fehler zum wirklichen Wert |(p-p_i)/p| \n"); // Beschreibung der ausgegebenen Groessen printf("# 4: Untergrenze a \n# 5: Obergrenze b \n"); // Beschreibung der ausgegebenen Groessen for(i=0; i<=N; ++i){ // Schleifen Anfang p = a + (b-a)/2; // Festlegung des x-Wertes in der Mitte des Intervalls [a,b] (x=p) fp = f(p); // Berechnung des f(p)-Wertes in der Mitte des Intervalls [a,b] printf("%3d %14.10f %14.10f %14.10f %14.10f %14.10f \n",i, p, fp, fabs((Loes-p)/Loes), a, b); // Ausgabe der berechneten Werte if( fa*fp > 0 ){ // Falls der berechnete Wert f(p) das gleiche Vorzeichen hat wie f(a), dann ... a = p; // ... setze die Untergrenze auf a=p und ... fa = fp; // ... lege den neuen Funktionswert an der Untergrenze fest: f(a)=f(p) } else if( fa*fp < 0 ){ // Falls der berechnete Wert f(p) ein unterschiedliches Vorzeichen hat wie f(a), dann ... b = p; // ... setze die Obergrenze auf b=p } else{ // Falls durch der berechnete Funktionswert gerade Null ist (f(p)=0 -> f(a)*f(p)=0), dann ... i = N; // ... beende das Bisektion-Verfahren vorzeitig } // else Ende } // Ende der for-Schleife des Bisektion-Verfahres }
Das initiale Intervall $[0.25,2.5]$ wird mittels der Methode der Bisektion in jedem Iterationsschritt halbiert und die untere linke Abbildung zeigt die Terminalausgabe des ausgeführten Programms.
Man erkennt schon hier, dass der approximierte Wert der Nullstelle der Funktion $f(x)$ nach 10 Iterationen gut mit dem Literaturwert des x-Wertes des Schnittpunktes ($x = 1.7729093296693715...$) übereinstimmt. Die nebenstehende linke Abbildung verdeutlicht den Algorithmus der Intervallhalbierung in unserem Beispiel. Die Abbildung wurde mittels des unten angegebenen Python-Skriptes erstellt, wobei zunächst die Terminalausgabe des C++ Programms in eine Datei umgeleitet wurde (' ./a.out > A4_1.dat ').
# Python Programm zum Plotten der berechneten Daten von (A4_1.cpp) import matplotlib.pyplot as plt # Python Bibliothek zum Plotten (siehe https://matplotlib.org/ ) import numpy as np # Python Bibliothek fuer Mathematisches (siehe https://numpy.org/ ) data = np.genfromtxt("./A4_1.dat") # Einlesen der berechneten Daten von A4_1.cpp plt.title(r'Methode der Bisektion (Intervallhalbierungsverfahren)') # Titel der Abbildung plt.ylabel(r'$g(x)=x^3 \, , \,\, h(x)=ln(x)+5$') # Beschriftung y-Achse plt.xlabel('x') # Beschriftung x-Achse x_interval=np.linspace(data[0,4], data[0,5], 200) # x-Intervall [a,b] als Liste von 200 Zahlen plt.plot(x_interval,x_interval**3, color="blue", label="g(x)") # Plotten der Funktion f(x) im Intervall [a,b] plt.plot(x_interval,np.log(x_interval)+5, color="green", label="h(x)") # Plotten der Funktion f(x) im Intervall [a,b] y_interval=np.linspace(x_interval[-1]**3, data[-1,1]**3, int(data[-1,0])+1) # y-Bereich zum Veranschaulichen der unterschiedlichen Intervalle for i in data[:,0]: # Schleife um die einzelnen Resultate der Nullstelle Bisektion zu plotten index=int(i) # Umwandlung des Laufindex in eine Integer Zahl plt.plot([data[index,4],data[index,5]],[y_interval[index],y_interval[index]], color="red") # Plotten des i-ten Intervalls plt.scatter(data[index,1],y_interval[index], marker='*', color="black", s=25) # Plotten des i-ten p-Wertes plt.legend(frameon=True, loc="lower right",fontsize=10) # Anordnung der Legende plt.savefig("A4_1.png", bbox_inches="tight") # Speichern der Abbildung als Bild plt.show() # Zusaetzliches Darstellen der Abbildung in einem separaten Fenster
Mittels des folgenden C++ Programms wurde zunächst die (x-y)-Wertetabelle, der vom Benutzer spezifizierten Funktion, ausgegeben.
// Musterlösung der Aufgabe 2 des Übungsblattes Nr.4 #include <iostream> // Ein- und Ausgabebibliothek #include <cmath> // Bibliothek für mathematisches (e-Funktion, Betrag, ...) using namespace std; // Benutze den Namensraum std double f(double x, int wahl){ // Deklaration und Definition der Funktion f(x) in Abhaengigkeit von der Funktionen-Auswahl double wert; // Deklaration des Rueckgabewertes der Funktion (y-Wert) switch( wahl ){ // switch-Anweisung Anfang case 1: // switch-Fall Nr.1 wert = exp(x) - 10; // Anweisung Funktion Nr.1 break; // switch-Fall Nr.1 Ende case 2: // switch-Fall Nr.2 wert = x*x - 10*x + 8; // Anweisung Funktion Nr.2 break; // switch-Fall Nr.2 Ende case 3: // switch-Fall Nr.3 wert = pow(x,3) - 8*x*x + 2*x + 3; // Anweisung Funktion Nr.3 break; // switch-Fall Nr.3 Ende case 4: // switch-Fall Nr.4 wert = 10 * exp(-x/5) * sin(3*x); // Anweisung Funktion Nr.4 break; // switch-Fall Nr.4 Ende default: // switch-default wert = 0; // Anweisung default break; // switch-default Ende } // switch-Anweisung Ende return wert; // Rueckgabewert der Funktion f(x) } // Ende der Funktion f(x) int main(){ // Hauptfunktion int auswahl; // Deklaration der Integer Variable der Funktionen-Auswahl const double plot_a = 0; // Untergrenze des x-Intervalls in dem die Ergebnisse ausgegeben werden sollen const double plot_b = 10; // Obergrenze des x-Intervalls in dem die Ergebnisse ausgegeben werden sollen const int N = 200; // Anzahl der Punkte in die das x-Intervall aufgeteilt wird const double dx = (plot_b - plot_a)/N; // Abstand dx zwischen den aequidistanten Punkten des x-Intervalls double x = plot_a - dx; // Aktueller x-Wert cin >> auswahl; // Einlesen Funktionsnummer mittels der Tastatur printf("# 0: Index i \n# 1: x-Wert \n# 2: f(x)-Wert \n"); // Terminal Ausgabe for(unsigned i = 0; i <= N; ++i){ // For-Schleife der Ausgabe der (x-y)-Wertetabelle x = x + dx; // Aktueller x-Wert printf("%3d %20.10f %20.10f \n",i, x, f(x,auswahl)); // Ausgabe der (x-y)-Wertetabelle } // Ende for-Schleife } // Ende der Hauptfunktion
Die Terminalausgabe des C++ Programms wurde hierbei in eine Datei umgeleitet (' ./a.out > A4_2.dat ') und die Funktionswerte dann mittels des folgenden Python Skriptes dargestellt:
# Python Programm zum Plotten (x-y)-Wertetabelle (A4_2.cpp) import matplotlib.pyplot as plt # Python Bibliothek zum Plotten (siehe https://matplotlib.org/ ) import numpy as np # Python Bibliothek fuer Mathematisches (siehe https://numpy.org/ ) data = np.genfromtxt("./A4_2.dat") # Einlesen der berechneten Daten von A4_2.cpp plt.title(r'Plot der gewählten Funktion') # Titel der Abbildung plt.ylabel(r'$f(x)$') # Beschriftung y-Achse plt.xlabel('x') # Beschriftung x-Achse plt.plot(data[:,1],data[:,2], color="blue") # Plotten der Funktion f(x) plt.savefig("A4_2.png", bbox_inches="tight") # Speichern der Abbildung als Bild plt.show() # Zusaetzliches Darstellen der Abbildung im separaten Fenster
echo Bitte geben Sie die Funktionsnummer ein: g++ A4_2.cpp ./a.out > A4_2.dat python3 PythonPlot_A4_2.py
Die Ausführung des C++ und Python Programms wurden in einem Shell Skript (A4_2.sh, siehe nebenstehende Abbildung) zusammengefügt, wobei die Anweisung, was der Benutzer einzugeben hat, in dem Shell Skript mittels des Befehles echo gemacht wurde.
Die folgenden Ausdrücke wurden mittels eines C++ Programms berechnet.
\[
\begin{equation}
\prod_{k=1}^{11} k^2 \quad,\quad \sum_{k=0}^{20} \sum_{i=0\\i \neq k}^{10} \frac{k + i^3}{\left( k - i \right)^2} \quad,\quad \hbox{Bestimmen Sie N}\quad:\quad \sum_{k=0}^{N} \sum_{i=0\\i \neq k}^{250} \left( k + i^2 \right) = 672013120
\end{equation}
\]
Die Lösungen der ersten und dritten Aufgabe können hierbei nur ganzzahlige Werte annehmen, sodass lediglich die Lösung der zweiten Aufgabe auf 15 Stellen genau und die der ersten und dritten Aufgabe als Integerzahlen ausgegeben wurden.
Das C++ Programm sah wie folgt aus
// Musterlösung der Aufgabe 3 des Übungsblattes Nr.4 #include <iostream> // Ein- und Ausgabebibliothek #include <cmath> // Bibliothek für mathematisches (e-Funktion, Betrag, ...) int main(){ // Hauptfunktion int k, i; // Deklaration der Summenindexe long A_1 = 1; // Deklaration der double Variable für Aufgabe 2.1 und Initialisierung double A_2 = 0; // Deklaration der double Variable für Aufgabe 2.2 und Initialisierung long A_3 = 0; // Deklaration der double Variable für Aufgabe 2.3 und Initialisierung for(k=1; k<=11; ++k){ // Schleifen Anfang A_1 = A_1 * k*k; // Produkt 1 } // Schleifen Ende for(k=0; k<=20; ++k){ // Schleifen Anfang der 1.Summe for(i=0; i<=10; ++i){ // Schleifen Anfang der 2.Summe if( i != k ){ // if-Anweisung Anfang A_2 = A_2 + (k + pow(i,3))/pow(k - i,2); //Innerer, math. Teil der Doppelsumme } // if-Anweisung Ende } // Schleifen Ende der 2.Summe } // Schleifen Ende der 1.Summe k=0; while( A_3 != 672013120 ){ // Schleifen Anfang 1.Summe, mit Abbruchbedingung for(i=0; i<=250; ++i){ // Schleifen Anfang der 2.Summe if( i != k ){ // if-Anweisung Anfang A_3 = A_3 + (k + i*i); //Innerer, math. Teil der Doppelsumme } // if-Anweisung Ende } // Schleifen Ende der 2.Summe ++k; // Erhöhung von k um eins wegen while-Schleife } // Schleifen Ende der 1.Summe // Terminal Ausgabe auf 15 Nachkommastellen printf("%-24s %-24s %-24s \n","Aufgabe 3.1","Aufgabe 3.2","Aufgabe 3.3, N="); printf("%-24li %-24.15f %-24i \n",A_1,A_2,k-1); }
und produzierte die folgende Terminalausgabe: