Felder sind in R die Verallgemeinerung von Matrizen. In einer Matrix werden die Komponenten zweidimensional angeordnet (Zeilen und Spalten), in einem Feld sind beliebige Dimensionen zugelassen. Erzeugt werden Felder meist, indem ein Vektor mit Hilfe des Dimensionsvektors mehrdimensional angeordnet wird, oder mit der Funktion outer(). Weitere Gemeinsamkeiten und Unterschiede zu Matrizen werden diskutiert.
Vorgestellt wird, wie Matrizen miteinander verknüpft werden, welche Funktionen Eigenschaften von Matrizen anzeigen, sowie zahlreiche Funktionen aus der Linearen Algebra (Berechnung von Determinanten, Lösung von linearen Gleichungssystemen, Berechnung von transponierten und inversen Matrizen, Berechnung von Eigenwerten und Eigenvektoren).
Die Komponenten eines Vektors können in R zweidimensional angeordnet werden wie in einer Matrix. Es werden verschiedene Möglichkeiten gezeigt, wie man Matrizen erzeugen kann, wie man spezielle Matrizen erzeugt und wie man auf die Komponenten einer Matrix zugreift. Weiter werden der Dimensionsvektor (Attribut dim) und das optionale Attribut dimnames vorgestellt. Wie Matrizen verknüpft werden und weitere Anwendungen folgen im nächsten Kapitel (Matrizen in R: Anwendungen).
Grundlegend für das Verständnis von Operationen, die mit Vektoren ausgeführt werden können, sind die punktweise Ausführung (eine Operation wird an die Komponenten weitergereicht) und der recycling-Mechanismus, der festlegt, wie Vektoren mit unterschiedlichen Längen verknüpft werden. Ausgehend hiervon werden zahlreiche Operationen vorgestellt, die mit Vektoren ausgeführt werden können (wie zum Beispiel statistische Funktionen, Sortier-Algorithmen, Mengen-Operationen).
Da es in R eigentlich keine fundamentalen Datentypen gibt (wie ganze Zahlen, Gleitkommazahlen, Zeichen, logische Werte), sondern diese Spezialfall eines Vektors der Länge 1 sind, ist dieses Kapitel entscheidend für das Verständnis von R. Vektoren bestehen aus Komponenten mit identischem Speichermodus und die Komponenten sind numeriert (oder wie man auch sagt: indiziert).
Vorgestellt werden hier Funktionen zum Erzeugen von Vektoren, der Zugriff auf die Komponenten eines Vektors, Diagnose-Funktionen für Vektoren und das Attribut names. Wie man Vektoren verknüpft und welche weiteren Funktionen zur Weiterverarbeitung von Vektoren existieren, wird im nächsten Kapitel gezeigt (Vektoren in R: Anwendungen).
Gezeigt wird, wie man in R die Zahlenbereiche für die Modi integer und double feststellen kann und wie man Zahlen in Potenz-Schreibweise eingeben kann. Ausführlich werden die Ausnahme-Werte Inf (Infinity), NaN (Not a Number), NA (Not Available) und NULL vorgestellt.
In R sind Zeichen kein fundamentaler Datentyp; sie werden nicht von Zeichenketten unterschieden. Um aber mit den Besonderheiten der Verarbeitung von Zeichen vertraut zu werden, werden vorerst nur Zeichen behandelt. Diese Besonderheiten betreffen insbesondere die Maskierung von bestimmten Zeichen und die Typumwandlungen. Einige harmlose Beispiele für Zeichenketten (die ohne Wissen über Vektoren verständlich sind) werden hier schon angeführt.
Übersicht über die folgenden Abschnitte, in denen die Komponenten des von Neumann-Rechners sowie die dazu nötigen elektrotechnischen Grundlagen behandelt werden.
Der Abschnitt behandelt die für den von Neumann-Rechner, insbesondere den Prozessor, relevanten elektrotechnischen Grundlagen:
Einführung in die Digitaltechnik, Transistoren, Schaltnetze und Schaltwerke.
Die Aufgaben des Betriebssystems haben sich im Lauf der Zeit gewandelt:
Anfangs war ein menschlicher Operator dafür zuständig, Programme zu starten und zu beenden, später wurde diese und weitere Aufgaben von Dienst-Programmen übernommen.
Um die Aufgaben und die Arbeitsweise des Betriebssystem besser zu verstehen, wird ein Computer in Schichten zerlegt: Anwendersoftware, Systemsoftware und Hardware.
Die wichtigsten Einteilungskriterien für Rechnernetze werden vorgestellt.
Aufgaben zum Selbststudium zum Kapitel Rechnerarchitektur.
Vorgestellt werden Festplatten als die wichtigsten externen Geräte eines von Neumann Rechners.
Ausführlich besprochen werden Aufbau und Funktionsweise der unterschiedlichen Arten von Festplatten .
Vorgestellt wird, wie der Hauptspeicher vom Prozessor über die Schnittstelle Adressregister und Datenregister angesprochen wird.
Der Hauptspeicher kann als statischer oder dynamischer Speicher realisiert sein (SRAM oder DRAM).
Für den Computer werden komplexe Operationen auf elementare Rechenoperationen heruntergebrochen. Deren wichtigste Gruppe sind logische Operationen, die hier ausführlich vorgestellt werden.
Vorgestellt wird die von Neumann Rechnerarchitektur und die wichtigsten Kenngrößen, die die Komponenten eines Computers charakterisieren.
Programmiersprachen werden eingesetzt, um Algorithmen zu schreiben.
Auszeichnungssprachen sind dazu da, um die Elemente eines Textes (wie Überschriften, Fließtext, Listen und dergleichen) logisch auszuzeichnen und meist Formatierungsregeln für diese Elemente festzulegen.
Als Beispiele für Auszeichnungssprachen werden LaTeX, HTML, XML und SVG vorgestellt.
Der Vorteil einer Auszeichnungssprache ist, dass sie sowohl menschen-lesbar als auch maschinen-lesbar ist, wodurch sie insbesondere in der automaischen Textverarbeitung eingesetzt wird.
Die Maschinensprache-Befehle sind noch nicht die elementaren Anweisungen für die Komponenten des Prozessors:
einen Maschinensprache-Befehl zu dekodieren heißt, ein Mikro-Programm zu laden, das den Befehl implementiert.
Je nach Prozessor-Architektur gibt es eine unterschiedlich große semantische Lücke zwischen den Maschinensprache-Befehlen und den Mikro-Befehlen.
Mit der Kenntnis der Mikro-Programme wird leichter verständlich, wie die Komponenten des Prozessors zusammenarbeiten und sie mit Hilfe des Pipelining optimal ausgelastet werden können.
Anwendungen aus verschiedensten Bereichen, in denen die bisher erlernten Konzepte von C++ eingesetzt werden können, werden als Programmier-Aufgaben formuliert.
Zu Aufgaben, die zu längeren Algorithmen führen, in denen insbesondere Bedingungs-Prüfungen und Alternativen vorkommen, werden einige Lösungshinweise gegeben.
Bedingung, Alternative und Mehrfachalternative sind die Kontrollstrukturen, die man einsetzen kann, um den Ablauf eines Programmes zu steuern.
Erklärt wird ihre Syntax in C++ und es werden einige Spitzfindigkeiten diskutiert, die man bei ihrer Verwendung kennen sollte.
Für das Erlernen der Sprache C++ ist dieser Abschnitt zentral: es werden die wichtigsten fundamentalen Datentypen ausführlich vorgestellt, also Zeichen, Boolesche Variable, ganze Zahlen und Gleitkommazahlen. Die Datentypen sind immer verknüpft mit den Operationen, die mit ihnen ausgeführt werden können. Weiter werden die Typumwandlungen (und die damit verbundenen Fehlerquellen) zwischen den fundamentalen Datentypen besprochen.
Aufgrund der Plattformabhängigkeit der fundamentalen Datentypen in C++ ist es für den Programmierer unerlässlich zu wissen, welcher Datentyp wieviel Speicherplatz belegt und insbesondere in welchen Zahlenbereichen die am häufigsten verwendeten Datentypen (wie short, int, float, double) fehlerfrei eingesetzt werden können.
Da man sich die Grenzen der Zahlenbereiche vermutlich nicht merken kann, sollte man zumindest wissen, wie man sie leicht feststellen kann.
Dazu werden die in Elementare Syntax von C++: Fundamentale Datentypen gestellten Aufgaben gelöst beziehungsweise Lösungshinweise gegeben.
Aufgaben zum Einüben der Arbeitstechniken, die in der strukturierten Programmierung angewendet werden.
Das Wettergeschen kann durch das sochastische Modell einer Markov-Kette simuliert werden. Die Programmieraufgabe beinhaltet, die Eigenschaften einer Markov-Kette zu diskutieren und zu beurteilen, ob das Wettergeschehen damit treffend beschrieben werden kann und wie das Modell durch weiteren Annahmen verbessert werden kann.
Vorgestellt werden mehrere Aufgaben, die als vierwöchige Projektarbeit zu lösen sind. Programmiert werden soll entweder im Sinne der strukturierten Programmierung oder (besser) im Sinne der objekt-orientierten Programmierung.
Die Programmieraufgabe behandelt ein typisches Problem der Datenverarbeitung: Messdaten werden laufend aufgenommen und sollen geeignet ausgewertet werden. Sie können: Erstens direkt angezeigt werden, zweitens sofort in andere relevante Daten umgerechnet und angezeigt werden oder drittens abgespeichert und erst in ihrer Gesamtheit ausgewertet werden. Diese Aufgaben sollen anhand der zu simulierenden Daten, die während einer Fahrradtour anfallen können, eingeübt werden.
Vorgestellt wird ein Problem der Regelungstechnik: Es soll die Umgebung eines Hauses und dessen Heizung simuliert werden. Dabei sollen in konstanten Zeitabständen die Außentemperatur und die Raumtemperatur gemessen werden und ein Algorithmus entwickelt werden, der dafür sorgt, dass die Raumtemperatur der vorgegebenen Soll-Temperatur möglichst nahe kommt.
Matching-Probleme treten dann auf, wenn zwischen zwei Gruppen eine Zuordnung hergestellt werden soll (jedem Bewerber soll eine Stelle vermittelt werden; jedem Gast soll ein Geschenk überreicht werden). Dabei können unterschiedliche Nebenbedingungen hinzutreten (ein Bewerber ist nur für bestimmte Stellen qualifiziert; nicht jedes Geschenk ist für jeden Gast geeignet). Bei kleinen Gruppengrößen können diese Zuordnungen meist direkt gefunden werden; im Allgemeinen versucht man Algorithmen zu formulieren, die die Zuordnungen finden. Matching-Probleme werden in der Graphentheorie behandelt. Die hier vorgestellten Programmieraufgaben sollen einige typische Fragestellungen aufzeigen.
Das Rucksackproblem gehört zur Klasse der Optimierungsprobleme. Dabei sollen aus einer Menge von Gegenständen diejenigen in den Rucksack gepackt werden, die den Wert seines Inhaltes maximieren. Für kleine Anzahlen von Gegenständen kann man die optimale Lösung leicht erraten. Für sehr große Anzahlen kann ein Algorithmus, der alle möglichen Bepackungen durchprobiert, unzumutbare Rechenzeit beanspruchen.
Es wird das Travelling Salesman Problem vorgestellt, für das verschiedene Algorithmen entwickelt werden sollen. Zudem ist eine spezielle Anordnung der Stationen des Handlungsreisenden gegeben, auf die die Algorithmen angewendet werden sollen.
Inhalt und Lernziele des Kapitels Einführung in die Programmierung.
Vorgestellt werden die Design-Prinzipien Komposition und Vererbung, die immer dann eingesetzt werden, wenn Klassen als Datenelemente nicht nur fundamentale Datentypen sondern ihrerseits Klassen enthalten.
Dabei werden weitere anspruchsvolle Konzepte von C++ erläutert: Der Polymorphismus (= Vielgestaltigkeit), Zeiger, das Überschreiben von Funktionen (function overriding) und Operatoren, Implementierung einer Baumstruktur.
Anfangs wurde die Entwicklung von Programmiersprachen als Abfolge von Generationen aufgefasst (binäre Maschinensprache, Assembler, prozedurale Programmiersprache).
Irgendwann wurde dies zu unübersichtlich, so dass man besser von Programmier-Paradigmen spricht, was die unterschiedliche Herangehensweise an ein zu lösendes Problem ausdrücken soll.
Die wichtigsten Paradigmen sind: imperative Programmierung, deklarative Programmierung, funktionale Programmierung, objekt-orientierte Programmierung.
Näher erläutert werden hier die strukturierte Programmierung (als Weiterentwicklung der imperativen Programmierung) und die objekt-orientierte Programmierung.
Es werden die grundlegenden Eigenschaften eines Algorithmus erläutert und der Computer als Maschine vorgestellt, die in der Lage ist, jeden beliebigen Algorithmus abzuarbeiten.
In der Erstellung von Algorithmen konzentriert man sich zunächst auf die Abfolge der Befehle, die in ihrer Gesamtheit das gegebene Problem (meist die Berechnung von Ausgabewerten aus Eingabewerten) lösen. Dabei gerät man schnell zur Frage, wie dabei auftretende veränderliche Größen modelliert werden.
Jede Programmiersprache bietet dazu fundamentale Datentypen an, auf denen gewisse Operationen ausgeführt werden können (wie etwa die ganzen Zahlen zusammen mit den Grundrechenarten).
Vorgestellt werden hier fundamentale Datentypen wie ganze Zahlen, Gleitkommazahlen, logische Werte und Zeichen.
Zu ihrem besseren Verständnis ist es nötig, in Grundzügen die Speicherorganisation kennenzulernen.
Die umgangssprachliche Formulierung eines Algorithmus sollte man nur verwenden, um sich zu übereugen, ob man die Problemstellung verstanden hat. Um die Strukturelemente eines Algorithmus hervorzuheben und damit die Programmierung vorzubereiten, ist eine Formulierung im Pseudocode vorzuziehen. Damit ist man schon näher an einer formalen Sprache, in der eine strenge Syntax eingehalten werden muss und Mehrdeutigkeiten wie in einer natürlichen Sprache nicht vorkommen.
Boolesche Variablen können die beiden Werte TRUE und FALSE annehmen. Sie entstehen zum Beispiel bei Vergleichsoperationen und können durch zahlreiche logische Operationen miteinander verknüpft werden. Insbesondere um Fallunterscheidungen zu formulieren und den Ablauf eines Programmes zu steuern, werden sie eingesetzt.
Um R-Programme schreiben und ausführen zu können, sind einige Vorbereitungen nötig: Installation von R, Installation einer Entwicklungsumgebung, Anlegen und Strukturierung eines Arbeitsverzeichnisses.
Diese Vorbereitungen und kleine erste Programme werden für den Programmier-Einsteiger erläutert.
Weiter werden viele Hinweise gegeben, wie man sich das Arbeiten mit R erleichtern kann.
Die Programmiersprache R besitzt ihr eigenes Konzept, wie die eingebauten Datentypen aufgebaut sind; es unterscheidet sich von vielen anderen Programmiersprachen darin, dass es nicht elementaren Datentypen gibt (wie Zahlen, Zeichen und logische Werte) und zusammengesetzte Datentypen (also zum Beispiel Vektoren von Zahlen). Sondern es gibt nur Vektoren; eine Zahl ist dann ein Spezialfall eines Vektors der Länge 1. Neben den Vektoren gibt es sehr viele weitere vorbereitete Datentypen, so dass man als Programmierer erst für sehr spezielle Anwendungen eigene Datentypen definieren muss. Es wird eine Übersicht über die Datentypen in R gegeben sowie die Vorgehensweise beschrieben, wie man mit ihnen vertraut werden kann.
In R gibt es eigentlich keine elementaren Datentypen (wie Zahlen, logische Werte oder Zeichen), sondern nur Vektoren.
Um die Rechenoperationen (Grundrechenarten, insbesondere Division mit Rest, wissenschaftliche Funktionen) für Zahlen besser kennenzulernen, werden hier Zahlen wie elementare Datentypen behandelt.
Zur Unterscheidung von ganzen Zahlen und Gleitkommazahlen benötigt man die Konzepte Modus und Speicher-Modus.
Es werden erste Beispiele gezeigt, wie man in R mit Variablen umgeht.
Mit den drei Zugriffs-Spezifikationen (access modifier) public, protected und private wird festgelegt, welche Klasse auf welche Datenelemente und Methoden zugreifen kann. Mit ihrer Hilfe lässt sich die Datenkapselung realisieren. Die Zugriffs-Spezifikation ist ein Bestandteil der Deklaration von Datenelementen und Methoden; es wird gezeigt, wie man die Deklarationen einer Klasse übersichtlich in einem UML-Diagramm darstellen kann. UML-Diagramme sind somit eines der wichtigsten Hilfsmittel beim Entwurf komplexer Programme.
Es wird gezeigt, welche Möglichkeiten es gibt in einen Artikel Quelltexte einzubinden.
In JBerries wird eine Variation von Mediawiki verwendet, um Texte zu verfassen.
Der Artikel gibt einen Überblick über die unterstützten Textauszeichnungen und verweist auf deren ausführliche Erläuterung.
Mit der in JBerries verwendeten Wiki-Syntax können Links auf Inhalte von JBerries und auf spezielle Kapitel-Überschriften gesetzt werden. Externe Links werden dagegen nur im Klartext dargestellt. Beim Einbinden von Graphiken muss zwischen üblichen Graphik-Formaten (wie jpg oder png) und Vektorgraphiken (svg) unterschieden werden.
Ein Konstruktor legt fest, welche Aktionen beim Erzeugen eines Objektes ausgeführt werden und sind daher ein zentraler Bestandteil einer Klasse. Wie Methoden können sie überladen werden. Die Eigenschaften von Konstruktoren (und des Destruktors, der beim Löschen eines Objektes aufgerufen wird), einige spezielle Konstruktoren (Default-Konstruktor, Kopier-Konstruktor) sowie das Delegations-Prinzip werden hier vorgestellt.
Die zentralen Begriffe zum Verständnis der objekt-orientierten Programmierung sind Klassse und Objekt: Die Klasse ist der allgemeine Bauplan für die konkreten Objekte.
Gezeigt wird die Syntax in C++, mit der Klassen angelegt werden, ihre Datenelemente und Methoden definiert werden, wie konkrete Objekte erzeugt werden und wie diese in anderen Programmen genutzt werden.
Funktionsaufrufe können in C++ entweder mit call by value oder call by reference realisiert werden; beide werden vorgestellt und diskutiert. Rekursionen ermöglichen oft schlanke Quelltexte, die aber schwerer verständlich sind als die entsprechende Implementierung mit Schleifen; einige Beispiele sollen an die Verwendung von Rekursionen heranführen. Die sogenannten Function Templates werden in der C++-Standard-Bibliothek oft eingesetzt; sie sind in einem gewissen Sinn eine Verallgemeinerung des Überladens von Funktionen.
Strukturierte Programmierung heißt vor allem, dass man wiederkehrende Quelltexte zu Unterprogrammen (Funktionen) zusammenfasst.
Dieser Abschnitt zeigt, wie Funktionen in C++ realisiert werden (genauer: wie sie definiert und aufgerufen werden).
Die Quelltexte lassen sich besser strukturieren, wenn man die Definition einer Funktion in Deklaration und Implementierung aufteilt.
Weiter wird das Überladen von Funktionen besprochen.
Um Beispiele zur strukturierten Programmierung zu zeigen, werden einige Funktionen vorgestellt, die mit den Klassen vector und array aus der Standard-Bibliothek arbeiten.
Weiter wird anhand der Beispiele das Konzept des Gültigkeitsbereiches näher erläutert, insbesondere werden Eigenschaften und Einsatz-Möglichkeiten von lokalen Variablen, globalen Variablen und lokalen static-Variablen diskutiert.
Wie im entsprechenden Kapitel zur Einführung in die Programmierung werden hier die kopfgesteuerte Schleife, die fußgesteuerte Schleife und die Schleife mit Zählvariable besprochen und einige Spitzfindigkeiten erklärt, die die C++-Syntax dazu bereithält.
Weiter wird anhand der Schleifen das sehr viel weiter reichende Konzept des Gültigkeitsbereiches (scope) einer Variable vorgestellt.
Die Entwicklungsumgebung Code::Blocks bietet mehrere Möglichkeiten, eine neue Datei oder ein neues Projekt anzulegen; die für den Anfänger relevanten Möglichkeiten werden vorgestellt.
Zudem kann man sehr viel produktiver arbeiten, wenn man die in der Entwicklungsumgebung enthaltenen Helfer kennt (Syntaxhervorhebung, Syntax-Vervollständigung, Code-Refactoring, Code-Schnipsel).
Für die ersten Programme bietet es sich an, Ausgaben und Einagben über die Konsole zu machen.
Die zugehörigen Befehle in C++ werden hier erläutert.
Zugleich werden die Programmbeispiele verwendet, um zahlreiche weiterreichende Konzepte zu erklären:
Präprozessor-Direktive, Kommentare, Namensräume, die besondere Bedeutung der main()-Methode, der Rückgabewert einer Funktion, Quelltextformatierung.
Um C++-Programme schreiben, compilieren und ausführen zu können, muss man sich eine geeignete Umgebung bereitstellen.
Es werden einige Möglichkeiten beschrieben; empfohlen wird die Entwicklungsumgebungen Code::Blocks, die es in einer Version mit integriertem MinGW-Compiler gibt.