C++ Programmier-Aufgaben: Anwendungen aus Numerik, Finanzmathematik, Kombinatorik, Auszeichnungssprachen

Anwendungen aus verschiedensten Bereichen, in denen die bisher erlernten Konzepte von C++ eingesetzt werden können, werden als Programmier-Aufgaben formuliert.

Einordnung des Artikels

In diesem Kapitel werden einige komplexere Anwendungen vorgestellt, die zeigen sollen, welche Aufgaben man mit den bisher erlernten elementaren Befehlen lösen kann. Sie sollen später im Sinne der strukturierten Programmierung überarbeitet werden (siehe C++: Aufgaben zur strukturierten Programmierung).

Berechnung von Wurzeln

Der Taschenrechner berechnet die Wurzel einer Zahl a > 0 nach der Rekursionsformel aus Abbildung 1. Möchte man etwa die Wurzel aus 5 berechnen, so wird a = 5 gesetzt (und nicht mehr verändert) und die Rekursionsformel startet mit x1 = 5; sie läuft so lange, bis sich die Ergebnisse innerhalb der vom Taschenrechner angezeigten Stellen nicht mehr verändern.

Abbildung 1: Rekursionsformel zur näherungsweisen Berechnung der Wurzel.Abbildung 1: Rekursionsformel zur näherungsweisen Berechnung der Wurzel.

Aufgabe:

Wie genau kann man die Wurzel aus 5 mit C++ berechnen,

  • wenn man den Datentyp float verwendet,
  • wenn man den Datentyp double verwendet?

Wie oft wird dabei jeweils in die Rekursionsformel eingesetzt?

Vergleichen Sie Ihre Ergebnisse mit dem des Taschenrechners.

Wieviele Rechenschritte hat der Taschenrechner benötigt?

Finanzmathematik

Verzinsung

Wird ein Kapital K0 so angelegt, dass es jährlich mit einem Zinssatz i verzinst wird und die Zinsen nicht ausgeschüttet werden (Zinseszins), so berechnet sich das Kapital Kn nach n Jahren durch:

Kn = K0 · (1 + i)n

(Achtung: Der Zinssatz i ist keine Prozentzahl)

Aufgabe:

Schreiben Sie ein Programm, bei dem K0, n, i eingegeben werden und der Kontostand nach j = 1, 2, ... , n Jahren ausgegeben wird.

Berechnen Sie im Vergleich dazu, wie groß das Kapital K(j) bei Ausschüttung ist. (Damit ist gemeint: Das Kapital K0 bleibt auf der Bank liegen, die Zinsen werden jährlich ausbezahlt und K (j) ist die Summe aus K0 und den nach j Jahren insgesamt ausbezahlten Zinsen.)

Tilgungsrechnung

Die beiden einfachsten Arten, wie ein Kredit zurückbezahlt werden kann, sind:

  • Ratentilgung
  • Annuitätentilgung.

Bei der Ratentilgung wird eine jährlich konstante Tilgung geleistet; zusätzlich müssen für die noch bestehende Restschuld Zinsen bezahlt werden — dadurch ist der jährlich zu bezahlende Gesamtbetrag (die Annuität) nicht konstant.

Bei der Annuitätentilgung wird jährlich ein konstanter Betrag zurückbezahlt (dieser Betrag ist die Annuität, die natürlich größer sein muss als die Zinsen auf den Kreditbetrag); wie sich die Annuität aus Tilgung und Zinsen zusammensetzt, ist dann auf den ersten Blick nicht erkennbar.

Die Berechnungen für die Annuitätentilgung werden aber deutlich einfacher, wenn man die jährliche Annuität vorgibt (wobei man dann meist die Annahme trifft, dass die letzte Annuität abweichen darf). Der Nachteil ist dann, dass man die Laufzeit erst angeben kann, wenn man den Tilgungsplan aufgestellt hat.

Die Ratentilgung ist leichter zu berechnen, die Annuitätentilgung wird in der Praxis häufiger angewandt. In der Tabelle in Abbildung 2 ist für einen Kredit über 100000 EUR der Tilgungsplan für den Fall der Annuitätentilgung dargestellt; dabei wird ein Zinssatz von 10 Prozent angenommen und der Kredit soll innerhalb von 4 Jahren zurückbezahlt werden.

Abbildung 2: Tilgungsplan für einen Kredit mit Annuitätentilgung, der innerhalb von 4 Jahren zurückbezahlt wird.Abbildung 2: Tilgungsplan für einen Kredit mit Annuitätentilgung, der innerhalb von 4 Jahren zurückbezahlt wird.

Aufgabe:

Schreiben Sie ein Programm, mit dem für beliebigen Kreditbetrag K, beliebigen Zinssatz p (in Prozent) und für beliebige Rückzahlungsdauer n (in Jahren) der Tilgungsplan aufgestellt wird; und zwar einmal für Ratentilgung und einmal für Annuitätentilgung. Im Fall der Annuitätentilgung sollen zwei Varianten angeboten werden:

  • die Annuität ist auch im letzten Jahr konstant (wie im Beispiel der Tabelle oben)
  • die letzte Annuität (für das (n+1)-te Jahr) kann abweichen, soll aber kleiner sein als die Annuität für die Jahre 1 bis n. Die Annuität für die ersten n Jahre soll eine möglichst glatte Zahl sein.

Rundungsfehler, die kleiner als ein Cent sind, können ignoriert werden.

Abzählprobleme

In der Kombinatorik werden Formeln hergeleitet, mit denen man bei vielen Zufalls-Experimenten abzählen kann, wieviele mögliche Ausgänge es gibt. Beispielsweise zeigt Abbildung 3 die Berechnung der Anzahl der Möglichkeiten beim Zahlenlotto 6 aus 49.

Abbildung 3: Anzahl der Möglichkeiten beim Zahlenlotto 6 aus 49.Abbildung 3: Anzahl der Möglichkeiten beim Zahlenlotto 6 aus 49.

Man kann die Formel leicht nachvollziehen:

  • Für die erste gezogene Zahl gibt es 49 Möglichkeiten,
  • für die zweite gezogene Zahl bleiben noch 48 Möglichkeiten, ...
  • für die sechste gezogene Zahl noch 44 Möglichkeiten.
  • Da man die Reihenfolge, in der die Zahlen gezogen werden, nicht voraussagen muss, liefern 6! mögliche Anordnungen der gezogenen Zahlen dasselbe Ergebnis der Ziehung.

Es lassen sich aber auch viele Probleme formulieren, für die eine entsprechende Formel nicht bekannt ist oder die so schwierig erscheinen, dass man nicht erwarten kann, in vernünftiger Zeit die Formel zu finden.

Um ein nicht ganz einfaches Beispiel zu nennen:

Ein Würfel wird viermal nacheinander geworfen und die vier Augenzahlen werden notiert.

  • Wieviele verschiedene Ergebnisse gibt es insgesamt bei diesem Experiment?
  • Bei wievielen Ergebnissen sind die Augenzahlen echt aufsteigend? (Die Folge 1246 ist echt aufsteigend, die Folge 1244 dagegen nicht.)

Die erste Frage ist noch leicht zu beantworten: Da der Würfel sechs verschiedene Ergebnisse liefern kann und die unabhängig voneinander kombiniert werden müssen, gibt es insgesamt 64 = 1296 Möglichkeiten.

Die zweite Frage ist schon deutlich schwieriger: Wenn im ersten Wurf eine 1 erscheint, gibt es für den zweiten Wurf noch 5 Möglichkeiten; die Anzahl der Möglichkeiten beim dritten Wurf hängt dann vom Ergebnis des zweiten Wurfes ab, ... Oder ist es einfacher, alle Möglichkeiten aufzuschreiben?

Hier kann ein Programm weiterhelfen: Man rechnet mit roher Gewalt (brute force) alle 64 = 1296 Möglichkeiten durch und entscheidet bei jeder Möglichkeit, ob die Bedingung echt aufsteigend erfüllt ist; man muss dann nur noch mitzählen.

Aufgaben:

Schreiben Sie zu folgenden Abzählproblemen ein C++-Programm, das alle möglichen Ergebnisse erzeugt und die gesuchten Ereignisse abzählt.

1. Ein Würfel wird viermal nacheinander geworfen und die vier Augenzahlen werden notiert.

  • Wieviele verschiedene Ergebnisse gibt es insgesamt bei diesem Experiment?
  • Bei wievielen Ergebnissen sind die Augenzahlen echt aufsteigend? (Die Folge 1246 ist echt aufsteigend, die Folge 1244 dagegen nicht.)
  • Bei wievielen Ergebnissen sind die Augenzahlen aufsteigend? (Die Folge 1244 ist aufsteigend, die Folge 1243 dagegen nicht.)

2. Ein Würfel wird sechsmal nacheinander geworfen und die sechs Augenzahlen werden notiert.

Wieviele Möglichkeiten gibt es, so dass mindestens zweimal nacheinander (egal wann) eine 6 erscheint?

Durch Abzählen erhält man hier:

1 · 1 · 6 · 6 · 6 · 6 = 1296 (6 im ersten Wurf, 6 im zweiten Wurf, beliebige Zahl im dritten Wurf,...)

5 · 1 · 1 · 6 · 6 · 6 = 1080 (keine 6 im ersten Wurf, 6 im zweiten Wurf, 6 im dritten Wurf, beliebige Zahl im vierten Wurf,...)

5 · 5 · 1 · 1 · 6 · 6 = 900

5 · 5 · 5 · 1 · 1 · 6 = 750

5 · 5 · 5 · 5 · 1 · 1 = 625

Es sind also insgesamt 4651 Möglichkeiten.

3. Jäger und Hasen:

Die folgende Abbildung 4 zeige j Jäger und h Hasen (im Spezialfall j = 4 = h), wobei gelten soll:

  • jeder Jäger zielt auf einen Hasen,
  • kein Jäger weiß, auf welchen Hasen die anderen Jäger zielen,
  • alle Jäger schießen einmal und gleichzeitig,
  • jeder Jäger trifft.

Abbildung 4: Vier Jäger zielen auf vier Hasen. Dargestellt ist eine mögliche Realisierung.Abbildung 4: Vier Jäger zielen auf vier Hasen. Dargestellt ist eine mögliche Realisierung.

Durch ein C++-Programm ist herauszufinden:

  • Wieviele mögliche Realisierungen gibt es bei diesem Szenario insgesamt (für j = 4 = h)?
  • Bei wievielen Möglichkeiten überleben null, ein, zwei beziehungsweise drei Hasen?
  • Wie groß ist der Erwartungswert der Anzahl der überlebenden Hasen?
  • Wie kann man das Programm verallgemeinern, so dass obige Fragen für beliebiges j und h beantwortet werden können?

Arbeiten mit Auszeichnungssprachen

Dieser Abschnitt schließt insbesondere an das Kapitel Auszeichnungssprachen (markup language) an: jetzt werden konkrete Aufgaben gestellt, die zeigen sollen, wie man Auszeichnungssprachen in der Praxis einsetzen kann. Oftmals werden Texte, die in einer Auszeichnungssprache vorliegen, gegenüber reinem Text als lediglich aufgebläht wahrgenommen, da der eigentliche Inhalt des Textes schwer herauszuarbeiten ist. In den Beispielen hier soll gezeigt werden, dass die Textverarbeitung durch die Verwendung von Auszeichnungssprachen aber deutlich erleichtert wird, da man gezielt auf Inhalte zugreifen kann beziehungsweise gegebene Inhalte besser aufbereiten kann.

Erzeugen von HTML-Tabellen

Der Quelltext einer HTML-Seite, die eine Überschrift und eine Tabelle enthält, könnte folgendermaßen aussehen:

<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
	table {border-collapse: collapse;}
	th, td {border: 1px solid #ddd; padding: 5px;}
</style>
<title="Liste von Quadratzahlen">
</head>
<body>
<h1>Quadratzahlen</h1>

<table>
	<tr>
		<th>n</th><th>n<sup>2</sup></th>
	</tr>
	<tr>
		<td>1</td><td>1</td>
	</tr>
	<tr>
		<td>2</td><td>4</td>
	</tr>
	<tr>
		<td>3</td><td>9</td>
	</tr>
	<tr>
		<td>4</td><td>16</td>
	</tr>
	<tr>
		<td>5</td><td>25</td>
	</tr>
	<tr>
		<td>6</td><td>36</td>
	</tr>
</table>

</body>

Die eigentlichen Inhalte der Tabelle befinden sich innerhalb des Elementes <table> ; die Darstellung der Tabelle wird durch die Anweisungen in <style> festgelegt (jede Zelle der Tabelle ist von einem Rahmen der Dicke 1 px mit hellgrauer Farbe umgeben; die Inhalte der Zellen haben in jeder Richtung vom Rahmen einen Abstand von 5 px).

Die Tabelle besteht aus zwei Spalten und insgesamt 7 Zeilen; davon ist die erste Zeile eine Kopfzeile (mit fett-gedruckten Überschriften) und 6 Zeilen mit den eigentlichen Tabellen-Inhalten. Dieser Quelltext erzeugt folgende Tabelle:

n n2
1 1
2 4
3 9
4 16
5 25
6 36

Die hier dargestellte Tabelle sollte mit derjenigen identisch sein, die Sie sehen, wenn Sie obigen Quelltext in einer .html-Datei abspeichern und mit dem Web-Browser öffnen. Der Grund liegt darin, dass die style-Information, die oben im Kopf der html-Datei definiert sind, ebenfalls in der .css-Datei der aktuellen Seite definiert sind:

<style>
	table {border-collapse: collapse;}
	th, td {border: 1px solid #ddd; padding: 5px;}
</style>

Um den Quelltext der Tabelle zu verstehen, muss man nur die entsprechenden html-Elemente kennen, sie sind in der folgenden Tabelle kurz erklärt:

Element Abkürzung für (oder Übersetzung) Bedeutung
table Tabelle Erzeugt eine html-Tabelle
tr table row = Tabellenzeile Zeile in einer Tabelle; muss dem Element table untergeordnet sein.
th table header = Tabellenkopf Kopfzelle einer Tabelle; muss dem Element tr untergeordnet sein. Anzahl pro Zeile: siehe td.
td table data = Tabellendaten Datenzelle; muss dem Element tr untergeordnet sein. Die Anzahl der Zellen pro Zeile sollte identisch sein (andernfalls muss man weitere Befehle einsetzen).

Aufgaben:

1. Schreiben Sie ein C++-Programm, das den einfachen Inhalt der Tabelle der Quadratzahlen als Konsolen-Ausgabe erzeugt. Mit einfachem Inhalt ist gemeint, dass nur die Tabellen-Zeilen erzeugt werden, also die Zeilen 13 bis 35 aus dem Quelltext oben.

2. Schreiben Sie ein C++-Programm, mit dem die Zahlen von 0 bis 255 in einer zwei-spaltigen html-Tabelle ausgegeben werden: In der ersten Spalte als Dezimalzahl, in der zweiten Spalte als Hexadezimalzahl.

Versuchen Sie das Programm so zu erweitern, dass in einer dritten Spalte die zugehörige Dualzahl ausgegeben wird.

Mit Ausgabe ist natürlich wieder gemeint, dass die entsprechende Konsolen-Ausgabe erzeugt wird. Wenn Sie diese Ausgabe in die html-Datei kopieren (anstelle von Zeile 13 bis 35), können Sie diese Tabelle mit dem Web-Browser ansehen.

3. Die folgende Tabelle zeigt einige pythagoreische Zahlen-Tripel, also Zahlen mit a2 + b2 = c2:

a b c
3 4 5
5 12 13
8 15 17
7 24 25
20 21 29
12 35 37
9 40 41
28 45 53
11 60 61
33 56 65
16 63 65
48 55 73
36 77 85
13 84 85
39 80 89
65 72 97
20 99 101
60 91 109
15 112 113
44 117 125
88 105 137
24 143 145
17 144 145
51 140 149
85 132 157
119 120 169
52 165 173
19 180 181
104 153 185
57 176 185
95 168 193
28 195 197

Formulieren Sie:

  • Welche pythagoreischen Zahlen-Tripel sind in der Tabelle dargestellt, welche fehlen?
  • Wie sind die Zahlen-Tripel angeordnet?

Schreiben Sie ein C++-Programm, das diese Zahlen-Tripel berechnet und die HTML-Tabelle erzeugt!

4. Wie kann man die logische Funktion XOR auf die elementaren Funktionen AND, OR und NOT zurückführen?

Schreiben Sie ein Programm, das die Tabelle (nicht die Schaltzeichen) der folgenden Abbildung als html-Tabelle erzeugt.

Abbildung 5: Logik-Tabelle und Schaltzeichen für die wichtigsten Booleschen Funktionen.Abbildung 5: Logik-Tabelle und Schaltzeichen für die wichtigsten Booleschen Funktionen.

So wie hier die html-Dateien mit Inhalten gefüllt werden, ist noch viel zu viel Handarbeit nötig (Konsolen-Ausgabe in Dateien kopieren und so weiter). Mit den Funktionen der Standard-Bibliothek zum Lesen und Schreiben von Dateien, kann man auch die Handarbeit automatisieren:

  • Man bereitet sich eine Datei header.html vor (etwa Zeile 1 bis 11 mit kleinen Anpassungen aus dem Quelltext oben).
  • Ebenso eine Datei footer.html (Zeile 36 bis 37).
  • Um die neue html-Datei aus der Konsolen-Ausgabe zu erzeugen, wird:
    1. eine neue (leere) Datei angelegt, etwa squares.html,
    2. der Inhalt von header.html in squares.html geschrieben,
    3. die Konsolen-Ausgabe nach squares.html umgeleitet,
    4. die Datei footer.html in squares.html geschrieben,
    5. die Datei squares.html geschlossen.

Sie können sich ein wenig in der C++-Dokumentation umsehen (Input/output library), ob Sie die entsprechenden Funktionen finden! Und es gibt natürlich zahlreiche Verbesserungen der hier vorgestellten Methode, um Ausgaben zu automatisieren.

Erzeugen von Vektorgraphiken

Skalierbare Vektorgraphiken (scalable vector graphics) können besonders leicht in html-Dateien eingebunden werden:

Zum Einen können sie wie andere Bilder (im Dateiformat .jpg oder .png) mit Hilfe des img-Elementes aufgerufen werden; der Quelltext dazu sieht dann etwa so aus:

<img src="img/graphik.svg" alt="Abbildung" width="1200" height="900">

Das Attribut src beschreibt den Pfad zur Datei graphik.svg.

Zum anderen können Vektorgraphiken direkt im Quelltext erstellt werden; dies ist ohne Verwendung des img-Elementes möglich. Dazu muss man wissen, dass skalierbare Vektorgraphiken eigentlich Textdateien sind; genauer sind es xml-Dateien (xml = extensible markup language), deren Elemente vom Browser als graphische Elemente interpretiert werden.

Darstellung zweidimensionaler Funktionen

Beispiel:

Der folgende Quelltext (in den body eines html-Quelltextes kopiert) erzeugt zwei Rechtecke und einen Kreis, die mit Farbe gefüllt sind:

<svg width="600" height="400">
	<rect width="400" height="200" style="fill:rgb(0,0,255);stroke-width:5;stroke:rgb(0,0,0)" />
	<rect x="400" y="0" width="50" height="300" stroke="gray" stroke-width="4" fill="rgb(255,128,0)" />
	<circle cx="100" cy="100" r="50" stroke="red" stroke-width="2" fill="yellow" />
</svg>

Werden diese Zeilen in den html-Quelltext eingebunden, wird in der html-Seite folgendes Bild dargestellt:

Abbildung 6: Testbild zur Erklärung (im Text unten) der Elemente in einer .svg-Datei.Abbildung 6: Testbild zur Erklärung (im Text unten) der Elemente in einer .svg-Datei.

Zur Erklärung:

  1. Durch die Attribute width und height im Element svg wird ein Koordinatensystem definiert, dessen Ursprung ist links oben; die x-Achse zeigt nach rechts, die y-Achse nach unten (Zeile 1).
  2. An der Definition der Rechtecke (Zeile 2 und 3) und des Kreises (Zeile 4) kann man dies leicht nachvollziehen.
  3. Das erste Rechteck besitzt keine absolute Ortsangabe sondern nur Breite und Höhe: es wird vom Ursprung aus mit diesen Angaben gezeichnet.
  4. Für das zweite Rechteck sind x- und y-Koordinate definiert, sie beschreiben den linken oberen Eckpunkt.
  5. Die Lage des Kreises erklärt sich von selbst. Da der Kreis im Quelltext nach dem Rechteck kommt, wird der Kreis über das Rechteck gezeichnet.
  6. Die Attribute, die die Farben des Rahmens (stroke) und der Füllung (fill) beschreiben, können mit style-Angaben definiert werden (Zeile 2) oder mit den Einzel-Attributen (Zeile 3 und 4).
  7. Farben können entweder mit Schlüsselworten (für vordefinierte Farben) oder im rgb-Modus (rot, grün, blau) angegeben werden. Im rgb-Modus werden die drei Farb-Komponenten mit ganzen Zahlen von 0 bis 255 angegeben. Die Angabe rgb(0,0,255) steht somit für blau.

Aufgaben:

1. Machen Sie eine kurze Kurvendiskussion (Nullstellen, Wertebereich, Verhalten am Rand des Definitionsbereiches) der Funktion

f(x,y) = x2 - y2, D = [ -1; +1 ] × [ -1; +1 ]

2. Der Definitionsbereich soll in Quadrate zerlegt werden. Der Funktionswert soll in eine geeignete Farbe übersetzt werden (etwa rot für positive Werte, blau für negative Wert, weiß für null). Überlegen Sie wie man ein Programm aufbauen kann, das die Funktionswerte über dem Definitionsbereich durch Farben sichtbar macht.

3. Eine mögliche Realisierung ist unten gezeigt (Abbildung 7). Wenn Sie Abbildung 7 abspeichern und mit einem Text-Editor öffnen, können Sie den Quelltext lesen. Er ist zwar sehr lang, aber seine Systematik sollte schnell erkennbar sein.

4. Darunter ist das C++-Programm, mit dem die Graphik erzeugt wurde (wie oben beschrieben, indem die Konsolen-Ausgabe in die html-Datei kopiert wurde). Das Programm ist im Sinne der strukturierten Programmierung geschrieben; versuchen Sie dennoch, das Programm zu verstehen.

Abbildung 7: Graphische Darstellung der Funktion f(x,y)  im oben angegebenen Definitionsbereich, indem die Funktionswerte in Farben übersetzt wurden.Abbildung 7: Graphische Darstellung der Funktion f(x,y) im oben angegebenen Definitionsbereich, indem die Funktionswerte in Farben übersetzt wurden.

Das Bild wurde mit Hilfe des folgenden Quelltextes erzeugt:

/* Programm zur Darstellung einer zweidimensionalen Funktion:
    die Funktionswerte über dem Definitionsbereich werden in Farben übersetzt
	Der Definitionsbereich wird durch 200 x 200 Pixel dargetellt, ein Quadrat im svg hat 8 x 8 Pixel
	200 = 8 x 25: zur Verallgemeinerung müsste man für 200, 8, 25 Variablen einführen.
*/

#include <iostream>

using namespace std;

// Breite und Höhe des Bildes: 200 Pixel, Auflösung zur Darstellung: 8 Pixel
const int WIDTH = 8;        // Breite des Rechtecks
const int HEIGHT = 8;       // Höhe des Rechtecks

/* f: Funktion, deren Höhe über dem Definitionsbereich farbig dargetellt werden soll
Achtung: der Def.bereich ist [-1;+1] x[-1;+1] und die Funktionswerte müssen in [-1;+1] liegen
(andernfalls liefern die 3 Funktionen für die Farben keine gültigen Werte
-> Funktion skalieren, falls Wertebereich nicht in [-1;+1]
*/
double f(double x, double y);

/* erzeugt svg-Quelltext für Rechteck mit Koordinaten x ,y (in Pixel) und rgb-Farbe, also r, g, b = 0,.., 255 */
void printRectangular(int x, int y, int r, int g, int b);

/* Funktionen, die den rgb-Anteil der Farbe in Abhängigkeit vom Funktionswert z in [-1; +1] berechnen */
int red(double z);
int green (double z);
int blue(double z);

/* löst Ausgabe aus, wird in main() aufgerufen */
void printSvg();

int main()
{
    printSvg();
    return 0;
}

double f(double x, double y){
    return x * x - y * y;
}

/* alternative Funktionen
double f(double x, double y){
    return 0.5 * (x * x + y * y);
}

double f(double x, double y){
    return  (x * x + y * y - 1);
}
*/

void printRectangular(int x, int y, int r, int g, int b){

    // <rect x="400" y="0" width="50" height="300" fill="rgb(255,128,0)" />
    cout << "<rect x = \"" << x << "\" y = \"" << y << "\" width=\"" << WIDTH <<
            "\" height=\"" << HEIGHT << "\" fill=\"rgb(" << r << "," << g << "," << b << "\)" />" << endl;
}

int red (double z){
    if (z < 0)
        return 0;
    return 255;
}

int green (double z){
    if (z < 0)
         z *= -1;
    int green = (1 - z) * 255;
    return green;
}

int blue (double z){
    if (z > 0)
        return 0;
    return 255;
}

void printSvg(){
    int x;      // Position in Pixel
    int y;      // Position in Pixel

    double x_D;     // Position im Definitionsbereich
    double y_D;     // Position im Definitionsbereich
    double z;           // Funktionswert bei (x_D, y_D), z = f(x,y) = x^2 - y^2

    for (int i = 1; i < 26; i++){      // x-Richtung
        for (int k = 1; k < 26; k++){      // y-Richtung
            x = 8 * i;
            y = 8 * k;
            x_D = static_cast<double> (8 * i) / 100 - 1;
            y_D = 1 - static_cast<double> (8 * k) / 100;
            z = f(x_D, y_D);
            printRectangular(x, y, red(z), green(z), blue(z));
        }
    }

Weitere Beispiele:

1. Darstellung der Funktion

g(x,y) = (x2 + y2) / 2, D = [ -1; +1 ] × [ -1; +1 ]

Abbildung 8: Graphische Darstellung der Funktion g(x,y) im oben angegebenen Definitionsbereich; wie im Beispiel oben werden die Funktionswerte in Farben übersetzt.Abbildung 8: Graphische Darstellung der Funktion g(x,y) im oben angegebenen Definitionsbereich; wie im Beispiel oben werden die Funktionswerte in Farben übersetzt.

2. Darstellung der Funktion

h(x,y) = x2 + y2 - 1, D = [ -1; +1 ] × [ -1; +1 ]

Abbildung 9: Graphische Darstellung der Funktion h(x,y) im oben angegebenen Definitionsbereich; wieder werden die Funktionswerte in Farben übersetzt.Abbildung 9: Graphische Darstellung der Funktion h(x,y) im oben angegebenen Definitionsbereich; wieder werden die Funktionswerte in Farben übersetzt.

Wurfparabeln

Die folgende Abbildung 10 zeigt drei Kugeln, die aus identischer Anfangsposition und betragsgleicher Anfangsgeschwindigkeit unter verschiedenen Winkeln abgeworfen werden; die Winkel betragen 30°, 45°, 60°. Dargestellt sind 50 Stroboskopaufnahmen zu 50 verschiedenen Zeitpunkten (in identischem Zeitabstand).

Abbildung 10: Stroboskopaufnahmen beim schiefen Wurf mit unterschiedlichen Abwurfwinkeln.Abbildung 10: Stroboskopaufnahmen beim schiefen Wurf mit unterschiedlichen Abwurfwinkeln.

In der Abbildung 11 sind sie als Animation gezeigt (zusätzlich eine vierte Wurfparabel zum Anfangswinkel 75°).

Abbildung 11: Wurfparabeln als Animation.Abbildung 11: Wurfparabeln als Animation.

Möglich gemacht werden Animationen in Vektorgraphiken durch das Element <animateMotion> , das hier nicht erklärt werden soll.

Aufgabe:

Schreiben Sie ein Programm, das mit den oben vorgestellten Methoden die Stroboskop-Aufnahmen der Wurfparabeln als svg-Graphik zeigt.

Informieren Sie sich, wie das Element <animateMotion> eingesetzt wird und schreiben Sie ein Programm, das die Wurfparabeln als Animation zeigt.

Pythagoreische Zahlen-Tripel

Weiter oben unter Erzeugen von HTML-Tabellen wurde eine Tabelle mit speziellen pythagoreischen Zahlen-Tripeln gezeigt; für die Tabelle wurde c < 200 gewählt.

Eine graphische Darstellung der entsprechenden pythagoreischen Zahlen-Tripel mit c < 1000 zeigt Abbildung 12.

Abbildung 12: Pythagoreische Zahlen-Tripel mit c &lt; 1000.Abbildung 12: Pythagoreische Zahlen-Tripel mit c < 1000.

Aufgabe:

Schreiben Sie ein C++-Programm, das die Zahlen-Tripel für Abbildung 12 berechnet und den Quelltext für die Vektorgraphik erzeugt.

Simulation von Schaltungen

Im Kapitel Die Komponenten des von Neumann Rechners wurden mehrere Schaltnetze und Schaltwerke besprochen. Da die Sprache C++ die logischen Operationen NOT, AND, OR bereitstellt und alle anderen logischen Operationen daraus aufgebaut werden können, ist es möglich Schaltungen in Programmen zu simulieren. Die Möglichkeit Schleifen zu bilden, erlaubt dann sämtliche Eingabewerte (bei Schaltnetzen) und zusätzlich sämtliche Speicherzustände (bei Schaltwerken) durchzuspielen.

Aufgaben:

1. Auslösen von Warnsignalen:

4 Temperaturmessfühler sollen nach bestimmten Regeln einen Alarm auslösen können; Dazu wird für jeden Fühler ein Schwellenwert festgelegt. Über zwei Steuerleitungen (s1 s0) können die Zahlen 0, 1, 2, 3 als Dualzahl übertragen werden. Das durch die Steuerleitungen übertragene Signal legt die Regeln fest, wann ein Alarm ausgelöst wird:

  • Zeigen die Steuerleitungen 00, wird kein Alarm ausgelöst (egal, was die Temperaturfühler anzeigen).
  • Zeigen die Steuerleitungen 1, 2 beziehungsweise 3 (als Dualzahl) wird Alarm ausgelöst, wenn 1, 2 beziehungsweise 3 Temperaturfühler den Schwellenwert überschreiten.

Geben Sie hierfür die logische Tabelle und die Realisierung als Schaltung an!

Schreiben Sie ein C++-Programm, das die Schaltung simuliert!

2. Flip-Flop mit NOT und NAND:

Abbildung 13 zeigt eine andere Realisierung des Flip-Flop als im Kapitel Die Komponenten des von Neumann Rechners: elektrotechnische Grundlagen besprochen wurde.

  • Analysieren Sie dieses Flip-Flop nach der dort vorgestellten Methode. Untersuchen Sie insbesondere ob es instabile und inkonsistente Zustände gibt.
  • Falls es instabile und inkonsistente Zustände gibt, nehmen Sie an, dass S gegenüber R dominiert (also S = 1 und R = 1 wird wie S = 1 und R = 0 behandelt).
  • Geben Sie die Tabelle an, die alle Eingabewerte und möglichen Speicherzustände durchspielt.
  • Schreiben Sie ein C++-Programm, das die Tabelle erzeugt.

Abbildung 13: Flip-Flop, das mit NOT und NAND realisiert ist.Abbildung 13: Flip-Flop, das mit NOT und NAND realisiert ist.

Alle Kommentare
Durch die Nutzung dieser Website erklären Sie sich mit der Verwendung von Cookies einverstanden. Außerdem werden teilweise auch Cookies von Diensten Dritter gesetzt. Genauere Informationen finden Sie in unserer Datenschutzerklärung sowie im Impressum.