Numerische Methoden

Aus Physik
Zur Navigation springen Zur Suche springen

Allgemeines

Ein paar Anmerkungen zum Thema "Objektorientierte Programmierung (OOP)"

Objektorientierte Programmierung ist bedeutend mehr als die Verwendung von Klassen!

Erst wenn man die grundlegenden Ideen wie Kapselung, Vererbung, Polymorphismus, ... verstanden hat und einsetzen kann, ist man in der Lage die Vorteile der OOP effizient zu nutzen.

Was sind aber nun die Vorteile (kein Anspruch auf Vollständigkeit):

  • Mit Hilfe der Kapselung können klare Zuständigkeiten geschaffen, und damit Seiteneffekte vermieden werden.
  • Einzelne Module können leichter wiederverwendet werden
  • Der Code wird leichter wartbar und erweiterbar
  • Durch die gegebene Strukturierung fällt es leichter den Code zu verstehen (auch für den Programmierer, wenn er seinen Code nach einer gewissen Zeit wieder anschaut) und sich in den Code einzuarbeiten
  • Bessere Kommunizierbarkeit. Einerseits ist auch hierbei die Strukur hilfreich, andererseits gibt es viele Tools zur Planung und Visualisierung des Designs.

Ist OOP nötig?
Zweifelsohne sind die (was den Codeumfang betrifft) kleinen Beispiele, die in der Numerische Methoden UE zu schreiben sind, problemlos mit "herkömmlicher" strukturierter Programmierung programmierbar. Natürlich kann man leicht grobe (Design-)Fehler einbauen, wie z.B. globale Variablen "unpassend" zu verändern, jedoch schützt auch OOP nicht vor falschem Vorgehen, Verdenkern und Fehldesign.
Zwar lassen sich die Vorteile der OOP schon bei solch kleinen Projekten nutzen, bei größeren und/oder wachsenden Systemen ist jedoch die Verwendung objektorienterter Konzepte beihahe unumgänglich. Mit "Strukturierter Programmierung" erstellter Code wird mit zunehmender Größe rapide unlesbarer und unwartbarer. Insbesondere globale Variablen und globale Sichtbarkeit der Funktionen stellen große Probleme dar. Am schlimmsten zeigen sich Designmängel wenn der Code refactored/geändert oder ein Teil daraus wiederverwendet werden soll.
Sollte also jemand vorhaben sich in Zukunft etwas mehr mit Anwendungsprogrammierung zu beschäftigen, so kommt man um das Thema OOP nicht herum. Z.B. ist jede bekanntere Library für die Erstellung von GUIs (QT, WxWidgets, MFC) objektorientiert.


Gegenüberstellung verschiedener Programmiersprachen

Matlab

Matlab ist sehr vielseitig anwendbar. Man kann es sowohl als konsolenbasierten Taschenrechner als auch für die Erstellung von Simulationsprogrammen mit graphischer Benutzeroberfläche und wunderschön bunten Ausgaben benutzen. - Und natürlich für eine Unmenge an Aufgaben die irgendwo dazwischen liegen.

Das Besondere an Matlab ist sicherlich, dass es speziell für Berechnungen mit Vektoren und Matritzen zugeschnitten ist. So bestehen z.B. viele Berechnungen, für die man in den anderen Programmiersprachen mindestens eine Schleife braucht, aus einem einzigen simplen Befehl. Selbstverständlich kann man dies jedoch nur dann nutzen, wenn man in der Matlab-Programmierweise denkt.

Weiters bringt Matlab eine Unmenge an Funktionen und Toolboxes, die man sich in anderen Programmiersprachen oftmals erst mit vielen Libraries selbst zusammensuchen muss, mit.

Ein weiterer Vorteil ist, dass man sehr schnell und einfach aussagekräftige Diagramme erstellen kann. Diese können auch gleich in diversen Formaten gespeichert und so leicht für Berichte u.Ä. verwendet werden.

Matlab ist jedoch nicht das allmächtige Wunderwerkzeug für den Physiker. Das sicherlich größte Problem ist, dass es wesentlich langsamer als compilierte Programme ist. Wenn man dann auch noch Schleifen programmiert, wo es möglich wäre Vektorrechnungen direkt zu benutzen, dann wird es nochmals wesentlich langsamer.

Matlab-Programme werden (üblicherweise) interpretiert, was heißt, dass man Matlab installiert haben muss, um ein Programm laufen lassen zu können. Zwar gibt es Matlab-Cmpiler, jedoch sind diese bei den mehr oder weniger offiziellen Studentenversionen meist nicht enthalten. Ein daraus resultierender Vorteil ist, dass Matlab-Scripts plattformunabhängig sind.

C

C ist eine imperative, eher alte (entwickelt in den 70ern), nicht allzu umfangreiche und standardisierte (ANSI-C) Sprache. Ein compiliertes (man kann C-Code nicht interpretieren) C-Programm läuft jedoch nur auf einer Plattform.

C ist nicht sehr abstrahiert, wodurch man sie relativ leicht erlernen kann, allerdings bringt sie wenig Komfort mit sich. Der Programmierer kann sehr viel machen, und damit auch viele Fehler, was insbesondere beim Thema "Pointer" oft zu unerklärlichen Abstürzen und langen Fehlersuchen führt.

Für C sind viele Bibliotheken, darunter die stets vorhandene Standard C Library, erhältlich, welche einem die wichtigsten Hilfsmittel für das Programmieren zur Verfügung stellen.

Eines der Hauptanwendungsgebiete ist die Systementwicklung. Einerseits kann man mit C sehr schnelle und hardwarenahe Programme entwickeln, andererseits gibt es für fast jeden Prozessor (vom Mikrocontroller bis zum High-Tech-Großrechner) einen Compiler. Obwohl die Verwaltung großer Projekte mit C eher schwierig ist, ist beinahe jeder Betriebssystemkern in C geschrieben, insbesondere Unix ist eng mit C verknüpft (C wurde für Unix entwickelt).

Eine ganz nette Kurzübersicht über C findet man im Wikipedia.

C++

C++ basiert auf C, was man insbesondere an der gleichen Syntax merkt, ist aber mehr als eine Bloße Erweiterung, da (insbesondere) mit Templates und Objektorientierung vollkommen neue, grundlegende Konzepte hinzugekommen sind. Weiters wurde die Standard-C-Library zur wesentlich umfangreicheren C++ Standardbibliothek mit der STL (Standard Template Library) ausgebaut, welche OO und Templates exzessiv verwendet.

C++ ist zwar eine objektorientierte Programmiersprache, man kann jedoch auch imperativ programmieren und einfach das sehr umfangreiche Angebot an (beinahe immer objektorientierten) C++ Bibliotheken ausnutzen, was aber natürlich nicht gerade "schön" ist. Dafür ist es jedoch auch mit C++ möglich, recht hardwarenahe zu programmieren.

Die meisten Vorteile gegenüber C resultieren aus der OO, hauptsächlich deshalb weil man so große Libraries und Programme übersichtlich gestalten, leicht warten und gut erweitern kann.

Häufige Anwendungen von C++ sind die Entwicklung von Anwendungssoftware mit grafischer Oberfläche, Grafik- und Spieleprogrammierung.

Auch hier bietet Wikipedia eine gute Übersicht (auch über einige Compiler).

Java

Java ist eine beinahe vollständig objektorientierte Sprache, deren Syntax sehr stark an C++ angelehnt ist. Oftmals wirkt es wie eine einfacher zu programmierende Version von C++, so ist z.B. das oftmals verwirrende und fehlerverursachende Konzept der Pointer in Java nicht vorhanden. Der Programmierer hat nicht so viel Macht wie in C oder C++, kann somit aber auch weniger Fehler produzieren.

Wenn man ein Java-Programm schreibt, so werden daraus *.class - Files generiert, welche dann von der Java Virtual Machine "interpretiert" werden. Dies hat den Vorteil, dass ein Class-File auf verschiedensten Betriebssystemen ausgeführt werden kann. Doch genau dies verursachte der größte Nachteil von Java: es war zu langsam. Jedoch ist es seit einiger Zeit möglich Java-Code auch mit einem Native Compiler zu compilieren, welcher ausführbaren Maschinencode, der allerdings nicht mehr plattformunabhängig ist, erzeugt.

Sehr beliebt ist Java für die Erstellung von Anwendungssoftware mit schönen Oberflächen und sog. Applets. Dies sind Anwendungen, die in eine Webseite eingebunden werden. Ein Vorteil von Java ist, dass man Klassen für sehr viele Funktionalitäten "mitkriegt", insbesondere neben GUI-Klassen auch welche für die verschiedensten neuen Technologien wie Datenbankanbindungen, Netzwerkdieste, ...

Hinweis: Die Java Version von Microsoft erfüllt nicht den Java-Standard (von Sun)

Übrigens sind Java und viele Java-Entwicklungsumgebungen frei erhältlich.

Java von Sun (Firma die Java entwickelt hat): SUN-Java

C/C++ - Spezifisches

Allozierung von Speicher

Statisches Anlegen

Wenn man zum Zeitpunkt der Programmierung weiß wie viel Speicher man benötigt, so kann man diesen mit dem [] Operator reservieren. Dieser hat dann die angegebene, fixe Größe und hat den selben Gültigkeitsbereich wie eine an dieser Stelle angelegte Variable.

Ein Beispiel:

 int int_array[100];

Auf den Inhalt des Arrays kann man mit int_array[0] bis int_array[99] zugreifen.


Die "C - Methode"

C beinhaltet keine automatische Verwaltung von dynamischem Speicher. Für diesen Zweck gibt es verschiedene Funktionen:

void* malloc(size_t size)

Damit wird Speicher der Größe size_t reserviert und ein Pointer auf diesen Speicherbereich zurückgegeben. Da die Funktion jedoch nicht weiß, für welchen Variablentyp dieser Speicher gedacht ist, erhält man "nur" einen void*, welchen man erst auf den passenden Typ casten wird/muss (Pflicht ist dies nur für C++ Compiler).

Ein typischer Aufruf sieht so aus:

 int* int_array = (int *)malloc(100*sizeof(int)); 

void* calloc(size_t num_elements, size_t element_size)

Offensichtlich verwendet dieser Befehl eine etwas andere Syntax, darüber hinaus wird der reservierte Speicher mit 0 initialisiert.

Unser Beispiel:

 int* int_array = (int *)calloc(100, sizeof(int)); 

void* realloc(void *ptr, size_t new_size)

Hin und wieder will man die Größe des reservierten Speichers ändern. Dies ist mit realloc möglich. Man darf allerdings nicht übersehen, dass man einen neuen Pointer zurückbekommt!

Wollten wir z.B. den oben reservierten Speicher verdoppeln:

 int_array = (int *)realloc(int_array, 200*sizeof(int)); 

void free(void *ptr)

Dynamisch angelegten Speicher muss man auch wieder freigeben, wofür free zuständig ist. Oftmals werden Pointer auf gerade freigegebenen Speicher sofort auf NULL gesetzt, damit man diesen nicht versehentlich weiter benutzt.

Freigeben unseres Arrays:

 free(int_array);
 int_array = NULL; 


Die "C++ - Methode"

In C++ sind die Befehle new und delete für die Speicherverwaltung zuständig. Und zwar für Objekte und Arrays von primitiven Typen (int, long, int*, ...). Dabei wird new der Typ des anzulegenden Speichers übergeben, und man erhält bereits einen passenden Pointer.

Hier ein paar Anwendungen:

 int* int_pointer = new int;
 int* int_array = new int[100];
 TestClass* test_class = new TestClass();
 delete int_pointer;
 delete int_array;
 delete test_class;


Benutzung von nrutil

Visualisierung der Daten

Es gibt mehrere Möglichkeiten die erstellten Daten hübsch auszugeben. Einige der für diese LV relevanten werden hier beschrieben

Compilierung und Projektaufbau

Die schnellste (Vorschlaghammer-) Methode

Der elegantere, umständliche Weg

Makefiles (elegant und schnell)

Ressourcen

Matlab - Spezifisches

Einiges findet sich auf den WIKI-Seiten der LV "Applikationssoftware und Programmierung"