🤪 Kapitel 1.06.1 - Das erste echte Programm mit Zuweisungen, Schleifen und einfachen Abfragen - Die Mandelbrot Menge

Anfang der 1990’er Jahre hat Karl Bihlmeier eine Comicfigur entwickelt, die bei Amiga Fans zum Kult wurde.
Es war „Hermann der User“, er beschäftigt sich mit den typischen Problemen eines Computer-Nerd in und mit seinem Umfeld.
Veröffentlicht wurden diese unter anderem im „Amiga Magazin“ des Markt & Technik Verlags.
Vielen Dank an Karl Bihlmeier für die Erlaubnis zur Veröffentlichung 😉
Es war „Hermann der User“, er beschäftigt sich mit den typischen Problemen eines Computer-Nerd in und mit seinem Umfeld.
Veröffentlicht wurden diese unter anderem im „Amiga Magazin“ des Markt & Technik Verlags.
Vielen Dank an Karl Bihlmeier für die Erlaubnis zur Veröffentlichung 😉
🤪 Eine kurze Übersicht zur Mandelbrot Menge
Es ist ja ein kleiner Fetisch von mir, bei allen Sprachen oder Frameworks zuerst immer ein Programm für die Mandelbrot Menge zu programmieren. Zu diesem Thema habe ich bereits eine eigene Playlist bei YouTube ↗ 📺 Grundlagen der C++ Programmieren mithilfe des Qt Framework - Alle TeileTrotzdem hier eine kurze Übersicht:
↗ Benoît B. Mandelbrot war ein Mathematiker der sich unter anderem sehr intensiv mit ↗ Fraktaler Geometrie beschäftigt hat. In die Popkultur hat es ende der 1970’er Jahre die graphische Darstellung der nach Ihm benannten ↗ “Mandelbrot Menge” geschafft, oder auch als “Apfelmännchen” bekannt.
🤪 Die Koordinaten in der Mandelbrot Menge
In der folgenden Grafik sind die Koordinaten dargestellt, welche ich in dem Programm “Mandelbrot” benutze, es handelt sich dabei um ↗ komplexe Zahlen.
Übersicht der Mandelbrot Menge
🤪 Die Programm Beschreibung
Alle C Programme haben meist den identischen Aufbau. Es gibt zwei Dateiendungen .c (Programm) und .h (Header).Beide Dateien liegen im Standard-Textformat vor und können mit jedem Texteditor bearbeitet werden. Ein Witz am Rande: Ein bestimmter Compiler verlangte früher(tm), das die Datei zwingend mit einer Leerzeile abgeschlossen wird. Ob dieses Verhalten heute immer noch in der Form vorliegt, kann ich nicht sagen…
Aktuelle Compiler sind in der Lage mit UTF8 Kodierten Texten umzugehen, es muss aber beachtet werden nur den klassischen US-ASCII Code (Mit 7 Bit) zu verwenden, sollte der Quellcode mit alten Compilern verarbeitet werden. Ältere Compiler haben teilweise ein unbestimmtes Verhalten bei Texten mit dem erweiterten ASCII Code.
- .c Dateien enthalten den Programmcode, es gibt keine Beschränkung wie viele Dateien in ein Projekt eingebunden werden können. Das Limit ist der freie Speicher auf der Projekt-Diskette 😎
- .h Dateien enthalten Prototypen und Konstanten. Was genau Prototypen sind, wird besprochen, wenn die Funktionen vorgestellt werden sowie die Übergabe von Argumenten.
🤔 Die Zeilen 1 - 15
In den meisten Programmiersprachen ist es üblich, dass ein kurzer Kommentar am Anfang eingefügt wird, welcher über die Funktion Auskunft gibt, Informationen zum Autor oder Versionshinweise beziehungsweise bekannte Probleme.In C (Ab ANSI-C 1999) beginnt ein Zeilenkommentar mit einem doppelten Slash “//“ - Wie in C++, alles folgende in der Zeile wird ignoriert.
Für Kommentare über mehrere Zeilen kann auch die klassische Form des Kommentars genutzt werden.
uint32_t Test = 4711; // Dies ist nur ein Testkommentar
uint64_t BigTest /* Hier steht der Kommentar */ = 0815; // Mitten in der Anweisung
/*
*
* Der Kommentar kann auch /\_ /\_
* über mehrere Zeilen /_____/
* erfolgen. (X)-(X)
*
*/
uint64_t BigTest /* Hier steht der Kommentar */ = 0815; // Mitten in der Anweisung
/*
*
* Der Kommentar kann auch /\_ /\_
* über mehrere Zeilen /_____/
* erfolgen. (X)-(X)
*
*/
🤔 Die Zeilen 18 - 20
Mit dem #include Keyword werden so genannte Header-Dateien eingebunden. Diese enthalten meist Prototypen für Funktionen, Konstanten oder (oft in älterem Code) auch Makros - Siehe weiter oben unter .h Dateien.Alle Keywords die mit einem Hash beginnen, werden vom Präprozessor verarbeitet.
#include "stdio.h" // Standard-Input-Output (Funktionen aus dem C-Standard)
#include "math.h" // Mathematische Funktionen und Konstanten
#include "complex.h" // Datentyp fuer Komplexe Zahlen
#include "math.h" // Mathematische Funktionen und Konstanten
#include "complex.h" // Datentyp fuer Komplexe Zahlen
🤔 Die Zeilen 22 - 35
Der Einsprung Punkt in jedem C-Programm - Diese Funktion muss immer existieren, sonst meldet der Linker einem Fehler, das die main() Funktion fehlt.Es gibt zwei Varianten. Die einfache, ohne Abfrage der Übergebenen Argumente durch das Betriebssystem. Diese wird im “Mandelbrot” Programm benutzt.
//+------------------------------------------------------------------------
//! Einsprung in das Programm, die main() Funktion muss in einem C Programm
//! immer existieren.
//+------------------------------------------------------------------------
//! Argumente :
//! Es werden keine Argumente übernommen
//!
//+------------------------------------------------------------------------
//! Rückgabewert :
//! \return int - Fehlercode (0 für alles OK, kein Fehler)
//!
//+------------------------------------------------------------------------
int main( )
{
// Alle Funktionen oder Blöcke werden in geschweifte Klammern { … } eingeschlossen.
// Der hier gezeigte Kommentierungsstil ist die Grundlage für das Hilfsprogramm “doxygen”,
// mit dessen Hilfe die technische Dokumentation des Quellcodes vereinfacht wird.
}
//! Einsprung in das Programm, die main() Funktion muss in einem C Programm
//! immer existieren.
//+------------------------------------------------------------------------
//! Argumente :
//! Es werden keine Argumente übernommen
//!
//+------------------------------------------------------------------------
//! Rückgabewert :
//! \return int - Fehlercode (0 für alles OK, kein Fehler)
//!
//+------------------------------------------------------------------------
int main( )
{
// Alle Funktionen oder Blöcke werden in geschweifte Klammern { … } eingeschlossen.
// Der hier gezeigte Kommentierungsstil ist die Grundlage für das Hilfsprogramm “doxygen”,
// mit dessen Hilfe die technische Dokumentation des Quellcodes vereinfacht wird.
}
In der erweiterten Variante werden die vom Betriebssystem übergebenen Argumente übernommen und können ausgewertet werden. Zu dieser Möglichkeit wird es ein eigenes Kapitel geben.
//+------------------------------------------------------------------------
//! Einsprung in das Programm, die main() Funktion muss in einem C Programm
//! immer existieren.
//+------------------------------------------------------------------------
//! Argumente :
//! \param [in] argc - Anzahl der übergebenen Argumente
//! \param [in] *argv[] - Liste aller Argumente als Zeiger im C-Stil
//!
//+------------------------------------------------------------------------
//! Rückgabewert :
//! \return int - Fehlercode (0 für alles OK, kein Fehler)
//!
//+------------------------------------------------------------------------
int main( int argc, char *argv[] )
{
// Alle Funktionen oder Blöcke werden in geschweifte Klammern { … } eingeschlossen.
// Der hier gezeigte Kommentierungsstil ist die Grundlage für das Hilfsprogramm “doxygen”,
// mit dessen Hilfe die technische Dokumentation des Quellcodes vereinfacht wird.
}
//! Einsprung in das Programm, die main() Funktion muss in einem C Programm
//! immer existieren.
//+------------------------------------------------------------------------
//! Argumente :
//! \param [in] argc - Anzahl der übergebenen Argumente
//! \param [in] *argv[] - Liste aller Argumente als Zeiger im C-Stil
//!
//+------------------------------------------------------------------------
//! Rückgabewert :
//! \return int - Fehlercode (0 für alles OK, kein Fehler)
//!
//+------------------------------------------------------------------------
int main( int argc, char *argv[] )
{
// Alle Funktionen oder Blöcke werden in geschweifte Klammern { … } eingeschlossen.
// Der hier gezeigte Kommentierungsstil ist die Grundlage für das Hilfsprogramm “doxygen”,
// mit dessen Hilfe die technische Dokumentation des Quellcodes vereinfacht wird.
}
🤔 Die Zeilen 36 - 54
Anlegen und initialisieren aller benötigten Startwerte für die Mandelbrot Menge als Konstanten. Dieser Teil ließt sich schlimmer, als er wirklich ist.-
const double complex K_Min = CMPLX( -1, -1.5 );
Ließt sich wie folgt von links nach rechts: -
const
Sagt aus, der die folgende Deklaration eine Konstante ist. Also das der Inhalt nicht mehr geändert werden kann. -
double
Es handelt sich um eine Gleitkommazahl mit doppelter Genauigkeit. -
complex
Es handelt sich um einen zusammengesetzten Datentyp, er Beschreibt eine Komplexe Zahl mit einem Real- und Imaginär Teil. -
K_Min
Ist der Name der neuen Konstante. -
=
Zuweisungs Operator. Der rechte Teil wird dem linken Teil zugewiesen. -
CMPLX ( < Realer Teil > , < Imaginärer Teil > )
CMPLX() ist ein Makro aus der Header-Datei complex.h und diese enthält Hilfsfunktionen um leichter mit Komplexen Zahlen umgehen zu können.
Also CMPLX( -1, -1.5 );
Setzt in der Konstanten K_Min den Realen Teil auf "-1" und den Imaginären Teil auf "-1.5"
Der Dezimaltrenner in C ist der Punkt (.), mit dem Komma (,) werden Argumente getrennt.
Das Semikolon (;) beendet den Ausdruck.
// Minimale Koordinaten (links/oben) Real- und Imaginaer Teil
const double complex K_Min = CMPLX( -1, -1.5 );
// Maximale Koordinaten (rechts/unten) Real- und Imaginaer Teil
const double complex K_Max = CMPLX( 2, 1.5 );
// Maximale Anzahl der Iterationen für einen Punkt
const int32_t Max_Iterationen = 32;
// Spalten (Breite) in der Ausgabe
const int32_t Spalten = 78;
// Zeilen (Hoehe) in der Ausgabe
const int32_t Zeilen = 22;
const double complex K_Min = CMPLX( -1, -1.5 );
// Maximale Koordinaten (rechts/unten) Real- und Imaginaer Teil
const double complex K_Max = CMPLX( 2, 1.5 );
// Maximale Anzahl der Iterationen für einen Punkt
const int32_t Max_Iterationen = 32;
// Spalten (Breite) in der Ausgabe
const int32_t Spalten = 78;
// Zeilen (Hoehe) in der Ausgabe
const int32_t Zeilen = 22;
🤔 Die Zeilen 60 - 70
Anlegen und initialisieren aller benötigten Variablen für die Berechnung der Mandelbrot MengeZuerst werden zwei double Variablen (Schritte_Spalten und Schritte_Zeilen) Deklariert, die die Schrittweite für beide Achsen enthalten. Sowie zwei Zählvariaben, auf der X-Achse (Cx) wird der Realteil durchlaufen und auf der Y-Ache (Cy) der Imaginärteil.
Die Makros creal( < Komplexe Zahl > ) und cimag( < Komplexe Zahl > ) lesen jeweils den Real- oder Imaginärteil einer Komplexen Zahl.
Die Schrittweite für beide Achsel ist jeweils der Absolutwert (Funktion: fabs( < Wert > )) vom Reateil von K_Min - K_Max beziehungsweise dem Imaginärteil von K_Min - K_Max. Geteilt durch die Anzahl der Spalten oder Zeilen.
double Schritte_Spalte; // Schrittweite der Koordinaten in den Spalten
double Schritte_Zeile; // Schrittweite der Koordinaten in den Zeilen
int32_t Cx; // Zählvariabe für die Spalten, zum Durchlaufen des Realteil
int32_t Cy; // Zählvariabe für die Zeilen, zum Duchlaufen des Imaginaerteil
// Berechne die Schrittweite für die Spalten (Vom Realteil aus K_Max bis K_Min)
Schritte_Spalte = fabs( creal( K_Max ) - creal( K_Min ) ) / Spalten;
// Berechne die Schrittweite für die Zeilen (Vom Imaginaerteil aus K_Max bis K_Min)
Schritte_Zeile = fabs( cimag( K_Max ) - cimag( K_Min ) ) / Zeilen;
double Schritte_Zeile; // Schrittweite der Koordinaten in den Zeilen
int32_t Cx; // Zählvariabe für die Spalten, zum Durchlaufen des Realteil
int32_t Cy; // Zählvariabe für die Zeilen, zum Duchlaufen des Imaginaerteil
// Berechne die Schrittweite für die Spalten (Vom Realteil aus K_Max bis K_Min)
Schritte_Spalte = fabs( creal( K_Max ) - creal( K_Min ) ) / Spalten;
// Berechne die Schrittweite für die Zeilen (Vom Imaginaerteil aus K_Max bis K_Min)
Schritte_Zeile = fabs( cimag( K_Max ) - cimag( K_Min ) ) / Zeilen;
🤔 Die Zeilen 72 - 77
Durchlaufen wird die Funktion: Z = Z^2 - CWobei Z und C komplexe Zahlen sind. Z und C wird ebenfalls vom Typ "double complex" Deklariert.
double complex Z; // Komplexe Zahl für Z
double complex C; // Komplexe Zahl für C (Der aktuell zu berechnende Punkt)
double complex C; // Komplexe Zahl für C (Der aktuell zu berechnende Punkt)
🤔 Die Zeile 85
Initialisiere die Koordinate für den aktuellen Punkt (Die Komplexe Zahl C). Gestartet wird links/oben.Über das Makro CMPLX() wird jetzt der Komplexen Zahl C folgendes zugewiesen:
Der Reale Teil entspricht dem Realteil von K_Min
Der Imaginäre Teil entspricht dem Imaginärteil von K_Max
C = CMPLX( creal( K_Min ), cimag( K_Max ) );
🤔 Die Zeilen 88 - 161
Das C-Keyword for( < Variable> ; < Bedingung > ; < Optionaler Ausdruck > ) ermöglicht es eine Schleife zu bilden. Wie immer in C wird der zur Schleife gehörende Block in geschweifte Klammern { ... } eingeschlossen.Zuerst wird die Zählvariable angegeben und ein Startwert zugewiesen, hier: Cy = 0
Dann kommt die Abbruch-Bedingung. Die Schleife wird sooft durchlaufen, solange die Bedingung "Wahr" ist. Hier: Cy < Zeilen (Cy muss kleiner als Zeilen sein)
Die Bedingung wird vor dem durchlaufen der Schleife geprüft. Die Argumente im der for() Anweisung werden durch Semikolon (;) getrennt.
Zum Schluss kommt ein optionaler Ausdruck, der am Ende der Schleife ausgeführt wird. Hier: Cy ++
Das bedeutet, das Cy um eins erhöht wird - Es ist die Kurzform für Cy = Cy + 1
// Durchlauf der Zeilen von oben nach unten (Entspricht dem Imaginaer Teil)
for( Cy = 0; Cy < Zeilen; Cy++ )
{
...
}
for( Cy = 0; Cy < Zeilen; Cy++ )
{
...
}
🤔 Die Zeile 94
Bevor eine Zeile berechnet werden kann, muss die Koordinate für die aktuelle Zeile zurückgesetzt werden. Der Reale Teil von C wird auf den Realen Teil von K_Min gesetzt, der Imaginäre Teil bleibt unverändert. C = CMPLX( creal( K_Min ), cimag( C ) );
🤔 Die Zeilen 96 - 152
Es wird eine Verschachtelte Schleife angelegt. Für jede Spalte (Cy) werden alle Punkte in einer Zeile (Cx) durchlaufen. Der Aufbau ist identisch wie in Zeile 88. for( Cx = 0; Cx < Spalten; Cx++ )
{
...
}
{
...
}
🤔 Die Zeile 103 und 107
Jetzt wird wirklich der aktuelle Punkt auf der Koordinate Cx,Cy berechnet.Z wird auf 0 gesetzt (Real- und Imaginärteil).
Sowie wird der Iterationszähler (Iterationen) auf 0 gesetzt. Der Zähler hat den Datentyp int8_t.
// Der Startwert von Z ist 0
Z = CMPLX( 0, 0 );
// Anzahl der Interationen für den aktuellen Punkt
// Setze den Startwert der Iterationen auf 0
int8_t Iterationen = 0;
Z = CMPLX( 0, 0 );
// Anzahl der Interationen für den aktuellen Punkt
// Setze den Startwert der Iterationen auf 0
int8_t Iterationen = 0;
🤔 Die Zeilen 118 - 129
Jetzt wird der zweite Typ für Schleifen in C eingeführt - Das Keyword while( < Bedingung > ){ ... } beziehungsweise do{ ... } while( < Bedingung >) Vom while() Keyword gibt es zwei Varianten:Die einfache erste Variante ist: while( < Bedingung > ){ ... }
Dabei wird zuerst geprüft, ob die Bedingung "Wahr" ist, bevor die Schleife durchlaufen wird. Die Schleife wird solange durchlaufen, bis die Bedingung "Falsch" wird. Eine Endlose Schleife kann also mit while( 1 ){ ... } konstruiert werden. Um eine Schleife - egal ob for() oder while() - vorzeitig zu unterbrechen gibt es das break; Keyword.
Ber der do{ ... } while( < Bedingung >) Variante wird die Schleife mindestens ein mal durchlaufen,bis die Abbruch Bedingung geprüft wird.
do { leitet die Schleife ein.
Z=( Z * Z ) - C; wendet die Formel an: Z = Z^2 - C
Der Iterationszähler wird um eins erhöht - Iterationen++;
} schliesst den while() Block ab.
Die Abbruch Bedingung besteht aus zwei Teilen:
1. Der Iterationszähler muss kleiner als Max_Iteration sein.
2. Die Komplexe Zahl C muss kleiner als 4 sein.
In C ist es möglich, logische Ausdrücke, logischen zu kombinieren. Die Zeile 126 kann ich - vereinfacht - so Darstellen:
Wenn der Ausdruck in A - logisches UND (&&) - und der Ausdruck in B beide "Wahr" sind, ist auch das Ergebnis "Wahr".
Alan Turing hätte jetzt gesagt: Wenn dieser Satz zerlegt wird, wird er verständlich 🤪
do
{
...
}
while (
( A ) &&
( B )
);
{
...
}
while (
( A ) &&
( B )
);
do
{
// Berechne den aktuellen Punkt
Z=( Z * Z ) - C;
// Erhoehe den Iterationszaehler
Iterationen++;
}
while ( // Fertig?
( Iterationen < Max_Iterationen ) &&
( ( creal( Z ) + cimag( Z ) ) < 4 )
);
{
// Berechne den aktuellen Punkt
Z=( Z * Z ) - C;
// Erhoehe den Iterationszaehler
Iterationen++;
}
while ( // Fertig?
( Iterationen < Max_Iterationen ) &&
( ( creal( Z ) + cimag( Z ) ) < 4 )
);
🤔 Die Zeile 132
Nach dem Abarbeiten der Schleife, wird der Real Teil von C um einen Schritt (Schritte_Spalte) erhöht, der Imaginäre Teil bleibt unverändert. // Erhoehe den Real Teil von C um einen Schritt
C = CMPLX( creal( C + Schritte_Spalte ), cimag( C ) );
C = CMPLX( creal( C + Schritte_Spalte ), cimag( C ) );
🤔 Die Zeilen 135 - 149
Es wird jetzt aus der Anzahl der Iteration eine "Farbe" berechnet, in diesem Fall ein ASCII-Zeichen. Dazu wird das if und else Keyword eingeführt. Mit if kann geprüft werden, ob ein Ausdruck "Wahr" ist, dann wird der folgende Block ausgeführt. Sollte der Ausdruck "Falsch" sein, wird der Block in else ausgeführt.🤔 Die Zeile 135
Es wies geprüft, ob Iteration identisch ( == entspricht der Binären Gleichheit) mit Max_Iterationen ist.🤔 Die Zeile 139
Wenn diese Bedingung zutrifft, wird nur ein Leerzeichen " " ausgegeben. Dazu wird wieder die Bekannte printf() Funktion genutzt. printf( " " );
🤔 Die Zeile 149
Wenn Iteration ungleich Max_Iterationen ist, wird die Anzahl der Iterationen in ein Zeichen umsetzen, beginnend ab dem ASCII-Code 48 (Code für die "0"). Iteration hat mindestens den Wert 1, deshalb wird in der printf() Anweisung der Wert 47 als Startwert angegeben, dieser entspricht dem Slash-Zeichen (/).Das Format-Zeichen %c Beschreibt ein einzelnes ASCII-Zeichen, welches in der Argumentenliste angegeben wird. Das '/' wird in den Code 47 übersetzt plus die Anzahl der Iterationen.
printf( "%c", '/' + Iterationen );
Bei der Maximalen Anzahl von 32 Iterationen sind folgende Zeichen möglich: 0123456789:;<=>?@ABCDEFGHIJKLMNOP
// Bestimme die "Farbe" des Punktes als ACSII-Art
if ( Iterationen == Max_Iterationen )
{
// Wenn die Maximale Iteration erreicht wurde
// ein Leerzeichen ausgeben
printf( " " );
}
else
{
// Sonst die Anzahl der Iterationen in ein Zeichen umsetzen, beginned ab
// dem ASCII-Code 48 (Code fuer die "0")
// Iteration hat mindestens den Wert 1, deshalb wird in der printf() Anweisung
// der Wert 47 als Startwert angegeben, dieser entspricht dem Slash-Zeichen (/)
// Bei der Maximalen Anzahl von 32 Iterationen sind folgende Zeichen moeglich:
// 0123456789:;<=>?@ABCDEFGHIJKLMNOP
printf( "%c", '/' + Iterationen );
}
if ( Iterationen == Max_Iterationen )
{
// Wenn die Maximale Iteration erreicht wurde
// ein Leerzeichen ausgeben
printf( " " );
}
else
{
// Sonst die Anzahl der Iterationen in ein Zeichen umsetzen, beginned ab
// dem ASCII-Code 48 (Code fuer die "0")
// Iteration hat mindestens den Wert 1, deshalb wird in der printf() Anweisung
// der Wert 47 als Startwert angegeben, dieser entspricht dem Slash-Zeichen (/)
// Bei der Maximalen Anzahl von 32 Iterationen sind folgende Zeichen moeglich:
// 0123456789:;<=>?@ABCDEFGHIJKLMNOP
printf( "%c", '/' + Iterationen );
}
🤔 Die Zeilen 152 - 156
Das } schliesst die Innere for( Cx ...) Schleife. Und gibt das Zeichen für eine neue Zeile aus (Newline).Achtung: Windows Benutzer müssen eventuell "\r\n" Schreiben. MS-DOS nutzt <Carrige Return> und <Newline> als Zeilenende.
}
// Neue Zeile
printf( "\n" );
// Neue Zeile
printf( "\n" );
🤔 Die Zeilen 158 - 164
Nach dem Berechnen des aktuellen Punktes in der aktuellen Zeile, wird in C der Imaginäre Teil um Schritte_Zeile erniedrigt. Der Reale Teil bleibt unangetastet.Mit dem } wird die äussere Schleife for( Cy ...) abgeschlossen.
Damit ist die komplette Menge Berechnet und das Programm wird mit return ( 0 ); beendet.
// Erniedrige den Imaginaeren Teil von C um einen Schritt
// Da die Grafik von oben nach unten aufgebaut wird
C = CMPLX( creal( C ), cimag( C ) - Schritte_Zeile );
}
return( 0 );
// Da die Grafik von oben nach unten aufgebaut wird
C = CMPLX( creal( C ), cimag( C ) - Schritte_Zeile );
}
return( 0 );
Alle Downloads zu diesem Projekt:
💾 Mandelbrot.c
💾 Mandelbrot.pro
Inhalt von: Mandelbrot.c
..1: //+------------------------------------------------------------------
..2: //|
..3: //| Projekt : Kapitel1 - Das erste echte Programm
..4: //|
..5: //| Projektbeschreibung : Demonstration der Mandelbrot Menge in C
..6: //| : mit der Ausgabe als ASCII-Art
..7: //| :
..8: //| Versionsnummer : V1.00
..9: //| Lauffähig unter : Alle Systeme / Compiler ab ANSI-C 2011
.10: //|
.11: //| Autor : Salomo Sokoll - ss@salomo-sokoll.de
.12: //| Programmierung mit C und C++ ohne ideologischen Ballast
.13: //| https://salomo-sokoll.de/Buch/C_CPP/index.html
.14: //|
.15: //+------------------------------------------------------------------
.16:
.17: // Einbinden aller benötigten Header-Dateien (.h)
.18: #include "stdio.h" // Standard-Input-Output (Funktionen aus dem C-Standard)
.19: #include "math.h" // Mathematische Funktionen und Konstanten
.20: #include "complex.h" // Datentyp fuer Komplexe Zahlen
.21:
.22: //+------------------------------------------------------------------------
.23: //! Einsprung in das Programm, die main() Funktion muss in einem C Programm
.24: //! immer existieren.
.25: //+------------------------------------------------------------------------
.26: //! Argumente :
.27: //! Es werden keine Argumente übernommen
.28: //!
.29: //+------------------------------------------------------------------------
.30: //! Rückgabewert :
.31: //! \return int - Fehlercode (0 für alles OK, kein Fehler)
.32: //!
.33: //+------------------------------------------------------------------------
.34: int main( )
.35: {
.36: // *
.37: // ** Anlegen und initialisieren aller benötigten Startwerte
.38: // ** für die Mandelbrot Menge als Konstanten
.39: // *
.40:
.41: // Minimale Koordinaten (links/oben) Real- und Imaginaer Teil
.42: const double complex K_Min = CMPLX( -1, -1.5 );
.43:
.44: // Maximale Koordinaten (rechts/unten) Real- und Imaginaer Teil
.45: const double complex K_Max = CMPLX( 2, 1.5 );
.46:
.47: // Maximale Anzahl der Iterationen für einen Punkt
.48: const int8_t Max_Iterationen = 32;
.49:
.50: // Spalten (Breite) in der Ausgabe
.51: const int32_t Spalten = 78;
.52:
.53: // Zeilen (Hoehe) in der Ausgabe
.54: const int32_t Zeilen = 22;
.55:
.56: // *
.57: // ** Anlegen und initialisieren aller benötigten Variablen
.58: // ** für die Berechnung der Mandelbrot Menge
.59: // *
.60: double Schritte_Spalte; // Schrittweite der Koordinaten in den Spalten
.61: double Schritte_Zeile; // Schrittweite der Koordinaten in den Zeilen
.62:
.63: int32_t Cx; // Zählvariabe für die Spalten, zum Durchlaufen des Realteil
.64: int32_t Cy; // Zählvariabe für die Zeilen, zum Duchlaufen des Imaginaerteil
.65:
.66: // Berechne die Schrittweite für die Spalten (Vom Realteil aus K_Max bis K_Min)
.67: Schritte_Spalte = fabs( creal( K_Max ) - creal( K_Min ) ) / Spalten;
.68:
.69: // Berechne die Schrittweite für die Zeilen (Vom Imaginaerteil aus K_Max bis K_Min)
.70: Schritte_Zeile = fabs( cimag( K_Max ) - cimag( K_Min ) ) / Zeilen;
.71:
.72: // *
.73: // * Durchlaufen wird die Funktion: Z = Z^2 - C
.74: // * Wobei Z und C komplexe Zahlen sind
.75: // *
.76: double complex Z; // Komplexe Zahl für Z
.77: double complex C; // Komplexe Zahl für C (Der aktuell zu berechnende Punkt)
.78:
.79: // *
.80: // * Initialisiere die Koordinate fuer den aktuellen Punkt (Die Komplexe Zahl C)
.81: // * Gestartet wird links/oben
.82: // * Der Real Teil entspricht Cx (Spalten)
.83: // * Der Imaginaere Teil entspricht Cy (Zeilen)
.84: // *
.85: C = CMPLX( creal( K_Min ), cimag( K_Max ) );
.86:
.87: // Durchlauf der Zeilen von oben nach unten (Entspricht dem Imaginaer Teil)
.88: for( Cy = 0; Cy < Zeilen; Cy++ )
.89: {
.90:
.91: // Durchlauf der Spalten von links nach rechts (Entspricht dem Rrealen Teil)
.92:
.93: // Zuruecksetzen der Spalte
.94: C = CMPLX( creal( K_Min ), cimag( C ) );
.95:
.96: for( Cx = 0; Cx < Spalten; Cx++ )
.97: {
.98: // *
.99: // * Berechne den aktuellen Punkt
100: // *
101:
102: // Der Startwert von Z ist 0
103: Z = CMPLX( 0, 0 );
104:
105: // Anzahl der Interationen für den aktuellen Punkt
106: // Setze den Startwert der Iterationen auf 0
107: int8_t Iterationen = 0;
108:
109: // *
110: // * Durchlaufen wird die Funktion: Z = Z^2 - C
111: // * Wobei Z und C komplexe Zahlen sind
112: // *
113: // * Abbruchkriterien:
114: // * - Maximale Anzahl der Iterationen ist erreicht
115: // * - Z >= 4
116: // *
117:
118: do
119: {
120: // Berechne den aktuellen Punkt
121: Z=( Z * Z ) - C;
122:
123: // Erhoehe den Iterationszaehler
124: Iterationen++;
125: }
126: while ( // Fertig?
127: ( Iterationen < Max_Iterationen ) &&
128: ( ( creal( Z ) + cimag( Z ) ) < 4 )
129: );
130:
131: // Erhoehe den Real Teil von C um einen Schritt
132: C = CMPLX( creal( C + Schritte_Spalte ), cimag( C ) );
133:
134: // Bestimme die "Farbe" des Punktes als ACSII-Art
135: if ( Iterationen == Max_Iterationen )
136: {
137: // Wenn die Maximale Iteration erreicht wurde
138: // ein Leerzeichen ausgeben
139: printf( " " );
140: }
141: else
142: {
143: // Sonst die Anzahl der Iterationen in ein Zeichen umsetzen, beginned ab
144: // dem ASCII-Code 48 (Code fuer die "0")
145: // Iteration hat mindestens den Wert 1, deshalb wird in der printf() Anweisung
146: // der Wert 47 als Startwert angegeben, dieser entspricht dem Slash-Zeichen (/)
147: // Bei der Maximalen Anzahl von 32 Iterationen sind folgende Zeichen moeglich:
148: // 0123456789:;<=>?@ABCDEFGHIJKLMNOP
149: printf( "%c", '/' + Iterationen );
150: }
151:
152: }
153:
154: // Neue Zeile
155: // Achtung: Windows Benutzer müssen eventuell "\r\n" Schreiben. MS-DOS nutzt <Carrige Return> und <Newline> als Zeilenende.
156: printf( "\n" );
157:
158: // Erniedrige den Imaginaeren Teil von C um einen Schritt
159: // Da die Grafik von oben nach unten aufgebaut wird
160: C = CMPLX( creal( C ), cimag( C ) - Schritte_Zeile );
161:
162: }
163:
164: return( 0 );
165: }
166:
Inhalt von: Mandelbrot.pro
..1: #+------------------------------------------------------------------
..2: #|
..3: #| Projekt : Kapitel1 - Das erste echte Programm
..4: #|
..5: #| Projektbeschreibung : Demonstration der Mandelbrot Menge in C
..6: #| : mit der Ausgabe als ASCII-Art
..7: #| :
..8: #| Versionsnummer : V1.00
..9: #| Lauffähig unter : Alle Systeme / Compiler ab ANSI-C 2011
.10: #|
.11: #| Autor : Salomo Sokoll - ss@salomo-sokoll.de
.12: #| Programmierung mit C und C++ ohne ideologischen Ballast
.13: #| https://salomo-sokoll.de/Buch/C_CPP/index.html
.14: #|
.15: #+------------------------------------------------------------------
.16:
.17: TARGET = Mandelbrot
.18: TEMPLATE = app
.19:
.20: SOURCES += Mandelbrot.c
💾 Mandelbrot.c
💾 Mandelbrot.pro
Inhalt von: Mandelbrot.c
..1: //+------------------------------------------------------------------
..2: //|
..3: //| Projekt : Kapitel1 - Das erste echte Programm
..4: //|
..5: //| Projektbeschreibung : Demonstration der Mandelbrot Menge in C
..6: //| : mit der Ausgabe als ASCII-Art
..7: //| :
..8: //| Versionsnummer : V1.00
..9: //| Lauffähig unter : Alle Systeme / Compiler ab ANSI-C 2011
.10: //|
.11: //| Autor : Salomo Sokoll - ss@salomo-sokoll.de
.12: //| Programmierung mit C und C++ ohne ideologischen Ballast
.13: //| https://salomo-sokoll.de/Buch/C_CPP/index.html
.14: //|
.15: //+------------------------------------------------------------------
.16:
.17: // Einbinden aller benötigten Header-Dateien (.h)
.18: #include "stdio.h" // Standard-Input-Output (Funktionen aus dem C-Standard)
.19: #include "math.h" // Mathematische Funktionen und Konstanten
.20: #include "complex.h" // Datentyp fuer Komplexe Zahlen
.21:
.22: //+------------------------------------------------------------------------
.23: //! Einsprung in das Programm, die main() Funktion muss in einem C Programm
.24: //! immer existieren.
.25: //+------------------------------------------------------------------------
.26: //! Argumente :
.27: //! Es werden keine Argumente übernommen
.28: //!
.29: //+------------------------------------------------------------------------
.30: //! Rückgabewert :
.31: //! \return int - Fehlercode (0 für alles OK, kein Fehler)
.32: //!
.33: //+------------------------------------------------------------------------
.34: int main( )
.35: {
.36: // *
.37: // ** Anlegen und initialisieren aller benötigten Startwerte
.38: // ** für die Mandelbrot Menge als Konstanten
.39: // *
.40:
.41: // Minimale Koordinaten (links/oben) Real- und Imaginaer Teil
.42: const double complex K_Min = CMPLX( -1, -1.5 );
.43:
.44: // Maximale Koordinaten (rechts/unten) Real- und Imaginaer Teil
.45: const double complex K_Max = CMPLX( 2, 1.5 );
.46:
.47: // Maximale Anzahl der Iterationen für einen Punkt
.48: const int8_t Max_Iterationen = 32;
.49:
.50: // Spalten (Breite) in der Ausgabe
.51: const int32_t Spalten = 78;
.52:
.53: // Zeilen (Hoehe) in der Ausgabe
.54: const int32_t Zeilen = 22;
.55:
.56: // *
.57: // ** Anlegen und initialisieren aller benötigten Variablen
.58: // ** für die Berechnung der Mandelbrot Menge
.59: // *
.60: double Schritte_Spalte; // Schrittweite der Koordinaten in den Spalten
.61: double Schritte_Zeile; // Schrittweite der Koordinaten in den Zeilen
.62:
.63: int32_t Cx; // Zählvariabe für die Spalten, zum Durchlaufen des Realteil
.64: int32_t Cy; // Zählvariabe für die Zeilen, zum Duchlaufen des Imaginaerteil
.65:
.66: // Berechne die Schrittweite für die Spalten (Vom Realteil aus K_Max bis K_Min)
.67: Schritte_Spalte = fabs( creal( K_Max ) - creal( K_Min ) ) / Spalten;
.68:
.69: // Berechne die Schrittweite für die Zeilen (Vom Imaginaerteil aus K_Max bis K_Min)
.70: Schritte_Zeile = fabs( cimag( K_Max ) - cimag( K_Min ) ) / Zeilen;
.71:
.72: // *
.73: // * Durchlaufen wird die Funktion: Z = Z^2 - C
.74: // * Wobei Z und C komplexe Zahlen sind
.75: // *
.76: double complex Z; // Komplexe Zahl für Z
.77: double complex C; // Komplexe Zahl für C (Der aktuell zu berechnende Punkt)
.78:
.79: // *
.80: // * Initialisiere die Koordinate fuer den aktuellen Punkt (Die Komplexe Zahl C)
.81: // * Gestartet wird links/oben
.82: // * Der Real Teil entspricht Cx (Spalten)
.83: // * Der Imaginaere Teil entspricht Cy (Zeilen)
.84: // *
.85: C = CMPLX( creal( K_Min ), cimag( K_Max ) );
.86:
.87: // Durchlauf der Zeilen von oben nach unten (Entspricht dem Imaginaer Teil)
.88: for( Cy = 0; Cy < Zeilen; Cy++ )
.89: {
.90:
.91: // Durchlauf der Spalten von links nach rechts (Entspricht dem Rrealen Teil)
.92:
.93: // Zuruecksetzen der Spalte
.94: C = CMPLX( creal( K_Min ), cimag( C ) );
.95:
.96: for( Cx = 0; Cx < Spalten; Cx++ )
.97: {
.98: // *
.99: // * Berechne den aktuellen Punkt
100: // *
101:
102: // Der Startwert von Z ist 0
103: Z = CMPLX( 0, 0 );
104:
105: // Anzahl der Interationen für den aktuellen Punkt
106: // Setze den Startwert der Iterationen auf 0
107: int8_t Iterationen = 0;
108:
109: // *
110: // * Durchlaufen wird die Funktion: Z = Z^2 - C
111: // * Wobei Z und C komplexe Zahlen sind
112: // *
113: // * Abbruchkriterien:
114: // * - Maximale Anzahl der Iterationen ist erreicht
115: // * - Z >= 4
116: // *
117:
118: do
119: {
120: // Berechne den aktuellen Punkt
121: Z=( Z * Z ) - C;
122:
123: // Erhoehe den Iterationszaehler
124: Iterationen++;
125: }
126: while ( // Fertig?
127: ( Iterationen < Max_Iterationen ) &&
128: ( ( creal( Z ) + cimag( Z ) ) < 4 )
129: );
130:
131: // Erhoehe den Real Teil von C um einen Schritt
132: C = CMPLX( creal( C + Schritte_Spalte ), cimag( C ) );
133:
134: // Bestimme die "Farbe" des Punktes als ACSII-Art
135: if ( Iterationen == Max_Iterationen )
136: {
137: // Wenn die Maximale Iteration erreicht wurde
138: // ein Leerzeichen ausgeben
139: printf( " " );
140: }
141: else
142: {
143: // Sonst die Anzahl der Iterationen in ein Zeichen umsetzen, beginned ab
144: // dem ASCII-Code 48 (Code fuer die "0")
145: // Iteration hat mindestens den Wert 1, deshalb wird in der printf() Anweisung
146: // der Wert 47 als Startwert angegeben, dieser entspricht dem Slash-Zeichen (/)
147: // Bei der Maximalen Anzahl von 32 Iterationen sind folgende Zeichen moeglich:
148: // 0123456789:;<=>?@ABCDEFGHIJKLMNOP
149: printf( "%c", '/' + Iterationen );
150: }
151:
152: }
153:
154: // Neue Zeile
155: // Achtung: Windows Benutzer müssen eventuell "\r\n" Schreiben. MS-DOS nutzt <Carrige Return> und <Newline> als Zeilenende.
156: printf( "\n" );
157:
158: // Erniedrige den Imaginaeren Teil von C um einen Schritt
159: // Da die Grafik von oben nach unten aufgebaut wird
160: C = CMPLX( creal( C ), cimag( C ) - Schritte_Zeile );
161:
162: }
163:
164: return( 0 );
165: }
166:
Inhalt von: Mandelbrot.pro
..1: #+------------------------------------------------------------------
..2: #|
..3: #| Projekt : Kapitel1 - Das erste echte Programm
..4: #|
..5: #| Projektbeschreibung : Demonstration der Mandelbrot Menge in C
..6: #| : mit der Ausgabe als ASCII-Art
..7: #| :
..8: #| Versionsnummer : V1.00
..9: #| Lauffähig unter : Alle Systeme / Compiler ab ANSI-C 2011
.10: #|
.11: #| Autor : Salomo Sokoll - ss@salomo-sokoll.de
.12: #| Programmierung mit C und C++ ohne ideologischen Ballast
.13: #| https://salomo-sokoll.de/Buch/C_CPP/index.html
.14: #|
.15: #+------------------------------------------------------------------
.16:
.17: TARGET = Mandelbrot
.18: TEMPLATE = app
.19:
.20: SOURCES += Mandelbrot.c
Programm Ausgabe:
3333336;5555557442222222222222222222222268555587444444444476633333333333333331
333333333685555574444222222222222222333685555744444444444666333333333333333331
333333333333685555:44444447655333333766555557444444444466633333333333333333333
3333333333333366855557444447668>7766655555744444444449668333333333333333333333
333333333333333376685555877:=?<;8:75555876444444444966833333333333333333333368
33333333333333334479668:7AKE A998776664444447966<5533333333333333333695555
4449666685555557:9877;=>;=? A=;;?=9:@;A987766695555533333333333366;5555557
4444444444477668=B L @:8666>855555:76444444766955555;7444
44444444444445;::K =:88777;:787789><666855555:7444444
555555555555557: B<;<@ EH ?@9777555587644444447
6666666666666668 H I>C<:?877<6684447665
222333333444455678;E
2222233333344688 G G>;9::8;77866784444<
222222333355557; @>@<> HJ ?;;9977855555;6674444
2222222666666798:L ;<>88<7787697:;<774446333335566644
22222444444444:?;E J 998866669785555866744333333333333336
2224444444475555=<;9799;=;= E@===8<<<;C65544444677555556663333333333333333
2444775555558667444446669?IE <;66557866774444444447;5555566333333333333333
555555556633333333333755559:=?9966<7855555866<44444444447855555963333333333333
155;633333333333333335566744;6:;944433333355866<444444444478555558633333333333
13333333333333333333866444444;5567333333222222222222222444447;5555556333333333
113333333333333333366444444475556633322222222222222222222222447:55555586333333
333333333685555574444222222222222222333685555744444444444666333333333333333331
333333333333685555:44444447655333333766555557444444444466633333333333333333333
3333333333333366855557444447668>7766655555744444444449668333333333333333333333
333333333333333376685555877:=?<;8:75555876444444444966833333333333333333333368
33333333333333334479668:7AKE A998776664444447966<5533333333333333333695555
4449666685555557:9877;=>;=? A=;;?=9:@;A987766695555533333333333366;5555557
4444444444477668=B L @:8666>855555:76444444766955555;7444
44444444444445;::K =:88777;:787789><666855555:7444444
555555555555557: B<;<@ EH ?@9777555587644444447
6666666666666668 H I>C<:?877<6684447665
222333333444455678;E
2222233333344688 G G>;9::8;77866784444<
222222333355557; @>@<> HJ ?;;9977855555;6674444
2222222666666798:L ;<>88<7787697:;<774446333335566644
22222444444444:?;E J 998866669785555866744333333333333336
2224444444475555=<;9799;=;= E@===8<<<;C65544444677555556663333333333333333
2444775555558667444446669?IE <;66557866774444444447;5555566333333333333333
555555556633333333333755559:=?9966<7855555866<44444444447855555963333333333333
155;633333333333333335566744;6:;944433333355866<444444444478555558633333333333
13333333333333333333866444444;5567333333222222222222222444447;5555556333333333
113333333333333333366444444475556633322222222222222222222222447:55555586333333
