Wintersemester 2011/2012
Helmut Seidl
Institut für Informatik
TU Münhen
Inhalt dieser Vorlesung:
•
Einführung in Grundkonzepte der Informatik;•
Einführung in Denkweisen der Informatik;•
Programmieren in Java.Ein Problem besteht darin, aus einer gegebenen Menge von
Informationen eine weitere (bisher unbekannte) Information zu
bestimmen.
Ein Algorithmus ist ein exaktes Verfahren zur Lösung eines
Problems, d.h. zur Bestimmung der gewünshten Resultate.
== ⇒
Ein Algorithmus beshreibt eine Funktion:
f : E → A
,wobei
E =
zulässige Eingaben,A =
möglihe Ausgaben.Niht jede Abbildung lässt sih durh einen Algorithmus realisieren!
(
↑
Berehenbarkeitstheorie)Das Verfahren besteht i.a. darin, eine Abfolge von Einzelshritten der
Verarbeitung festzulegen.
Beispiel: Alltagsalgorithmen
Resultat Algorithmus Einzelshritte
Pullover Strikmuster eine links, eine rehts
eine fallen lassen
Kuhen Rezept nimm 3 Eier ...
Konzert Partitur Noten
Problem: Seien
a, b ∈ N , a, b 6= 0
. BestimmeggT (a, b)
.Algorithmus:
1. Falls
a = b
, brih Berehnung ab, es giltggT (a, b) = a
.Ansonsten gehe zu Shritt 2.
2. Falls
a > b
, ersetzea
durha − b
undsetze Berehnung in Shritt 1 fort.
Ansonsten gehe zu Shritt 3.
3. Es gilt
a < b
. Ersetze b durhb − a
undsetze Berehnung in Shritt 1 fort.
Problem: Seien
a, b ∈ N , a, b 6= 0
. BestimmeggT (a, b)
.Algorithmus:
1. Falls
a = b
, brih Berehnung ab, es giltggT (a, b) = a
.Ansonsten gehe zu Shritt 2.
2. Falls
a > b
, ersetzea
durha − b
undsetze Berehnung in Shritt 1 fort.
Ansonsten gehe zu Shritt 3.
3. Es gilt
a < b
. Ersetze b durhb − a
undsetze Berehnung in Shritt 1 fort.
Programmiersprahe.
Die Formulierung gestattet (hoentlih) eine mashinelle
Ausgeführung.
Beahte:
•
Es gibt viele Programmiersprahen: Java, C, Prolog, Fortran, Cobol ....•
Eine Programmiersprahe ist dann gut, wenn•
die Programmiererin in ihr ihre algorithmishen Ideennatürlih beshreiben kann, insbesondere selbst später noh
versteht, was das Programm tut (oder niht tut);
•
ein Computer das Programm leiht verstehen und ezientausführen kann.
Eine Programmiersprahe soll
•
Datenstrukturen anbieten;•
Operationen auf Daten erlauben;•
Kontrollstrukturen zur Ablaufsteuerung bereit stellen.Als Beispiel betrahten wir MiniJava.
Um Daten zu speihern und auf gespeiherte Daten zugreifen zu
können, stellt MiniJava Variablen zur Verfügung. Variablen müssen
erst einmal eingeführt, d.h. deklariert werden.
Beispiel:
int x, result;
Diese Deklaration führt die beiden Variablen mit den Namen x und
result ein.
•
Das Shlüsselwort int besagt, dass diese Variablen ganze Zahlen (Integers) speihern sollen.int heiÿt auh Typ der Variablen x und result.
•
Variablen können dann benutzt werden, um anzugeben, aufwelhe Daten Operationen angewendet werden sollen.
•
Die Variablen in der Aufzählung sind durh Kommas ,getrennt.
•
Am Ende steht ein Semikolon ;.Die Operationen sollen es gestatten, die Werte von Variablen zu
modizieren. Die wihtigste Operation ist die Zuweisung.
Beispiele:
•
x = 7;Die Variable x erhält den Wert 7.
•
result = x;Der Wert der Variablen x wird ermittelt und der Variablen
result zugewiesen.
•
result = x + 19;Der Wert der Variablen x wird ermittelt, 19 dazu gezählt und
dann das Ergebnis der Variablen result zugewiesen.
•
result = x - 5;Der Wert der Variablen x wird ermittelt, 5 abgezogen und dann
das Ergebnis der Variablen result zugewiesen.
Ahtung:
•
Java bezeihnet die Zuweisung mit =anstelle von :=(Erbshaft von C ...)
•
Jede Zuweisung wird mit einem Semikolon ; beendet.•
In der Zuweisung x = x + 1; greift das x auf der rehten Seiteauf den Wert vor der Zuweisung zu.
bzw. ausgeben zu können.
•
x = read();Diese Operation liest eine Folge von Zeihen vom Terminal ein
und interpretiert sie als eine ganze Zahl, deren Wert sie der
Variablen x als Wert zu weist.
•
write(42);Diese Operation shreibt 42 auf die Ausgabe.
•
write(result);Diese Operation bestimmt den Wert der Variablen result und
shreibt dann diesen auf die Ausgabe.
•
write(x-14);Diese Operation bestimmt den Wert der Variablen x,
subtrahiert 14 und shreibt das Ergebnis auf die Ausgabe.
•
Das Argument der write-Operation in den Beispielen ist ein int.•
Um es ausgeben zu können, muss es in eine Folge von Zeihenumgewandelt werden, d.h. einen String.
Damit wir auh freundlihe Worte ausgeben können, gestatten wir
auh direkt Strings als Argumente:
•
write("Hello World!");... shreibt Hello World! auf die Ausgabe.
Sequenz:
int x, y, result;
x = read();
y = read();
result = x + y;
write(result);
•
Zu jedem Zeitpunkt wird nur eine Operation ausgeführt.•
Jede Operation wird genau einmal ausgeführt. Keine wird wiederholt, keine ausgelassen.•
Die Reihenfolge, in der die Operationen ausgeführt werden, ist die gleihe, in der sie im Programm stehen (d.h. naheinander).•
Mit Beendigung der letzten Operation endet dieProgramm-Ausführung.
== ⇒
Sequenz alleine erlaubt nur sehr einfahe Programme.int x, y, result;
x = read();
y = read();
if (x > y)
result = x - y;
else
result = y - x;
write(result);
•
Zuerst wird die Bedingung ausgewertet.•
Ist sie erfüllt, wird die nähste Operation ausgeführt.•
Ist sie niht erfüllt, wird die Operation nah dem elseausgeführt.
•
Statt aus einzelnen Operationen können die Alternativen auh aus Statements bestehen:int x;
x = read();
if (x == 0)
write(0);
else if (x < 0)
write(-1);
else
write(+1);
•
... oder aus (geklammerten) Folgen von Operationen und Statements:int x, y;
x = read();
if (x != 0) {
y = read();
if (x > y)
write(x);
else
write(y);
} else
write(0);
•
... eventuell fehlt auh der else-Teil:int x, y;
x = read();
if (x != 0) {
y = read();
if (x > y)
write(x);
else
write(y);
}
Auh mit Sequenz und Selektion kann noh niht viel berehnet
werden ...
int x, y;
x = read();
y = read();
while (x != y)
if (x < y)
y = y - x;
else
x = x - y;
write(x);
•
Zuerst wird die Bedingung ausgewertet.•
Ist sie erfüllt, wird der Rumpf des while-Statements ausgeführt.•
Nah Ausführung des Rumpfs wird das gesamtewhile-Statement erneut ausgeführt.
•
Ist die Bedingung niht erfüllt, fährt die Programm-Ausführung hinter dem while-Statement fort.berehenbar ist, läÿt sih mit Selektion, Sequenz, Iteration,
d.h. mithilfe eines MiniJava-Programms berehnen !!
Beweis:
↑
Berehenbarkeitstheorie.Idee:
Eine Turing-Mashine kann alles berehnen...
Versuhe, eine Turing-Mashine zu simulieren!
Man muss sie nur geeignet dekorieren !
Man muss sie nur geeignet dekorieren !
Beispiel: Das GGT-Programm
int x, y;
x = read();
y = read();
while (x != y)
if (x < y)
y = y - x;
else
x = x - y;
write(x);
Daraus wird das Java-Programm:
publi lass GGT extends MiniJava
{
publi stati void main (String[℄ args)
{
int x, y;
x = read();
y = read();
while (x != y)
if (x < y)
y = y - x;
else
x = x - y;
write(x);
} //
Ende der Definition von main();} //
Ende der Definition der Klasse GGT;•
Jedes Programm hat einen Namen (hier: GGT).•
Der Name steht hinter dem Shlüsselwort lass (was eine Klasse, was publi ist, lernen wir später)•
Der Datei-Name muss zum Namen des Programms passen,d.h. in diesem Fall GGT.java heiÿen.
•
Das MiniJava-Programm ist der Rumpf des Hauptprogramms, d.h. der Funktion main().•
Die Programm-Ausführung eines Java-Programms startet stets mit einem Aufruf von dieser Funktion main().•
Die Operationen write() und read() werden in der Klasse MiniJava deniert.•
Durh GGT extends MiniJava mahen wir dieseimport javax.swing.JOptionPane;
import javax.swing.JFrame;
publi lass MiniJava {
publi stati int read () {
JFrame f = new JFrame ();
String s = JOptionPane.showInputDialog (f, "Eingabe:");
int x = 0; f.dispose ();
if (s == null) System.exit (0);
try { x = Integer.parseInt (s.trim ());
} ath (NumberFormatExeption e) { x = read (); }
return x;
}
publi stati void write (String x) {
JFrame f = new JFrame ();
JOptionPane.showMessageDialog (f, x, "Ausgabe",
JOptionPane.PLAIN_MESSAGE);
f.dispose ();
}
publi stati void write (int x) { write (""+x); }
}
•
Jedes Programm sollte Kommentare enthalten, damit man sihselbst später noh darin zureht ndet!
•
Ein Kommentar in Java hat etwa die Form:// Das ist ein Kommentar!!!
•
Wenn er sih über mehrere Zeilen erstreken soll, kann er auhso aussehen:
/* Dieser Kommentar geht
"uber mehrere Zeilen! */
Auf der Kommandozeile sieht das so aus:
seidl> java GGT.java
seidl> java GGT
•
Der Compiler java liest das Programm aus den DateienGGT.java und MiniJava.java ein und erzeugt für sie
JVM-Code, den er in den Dateien GGT.lass und
MiniJava.lass ablegt.
•
Das Laufzeitsystem java liest die Dateien GGT.lass und MiniJava.lass ein und führt sie aus.•
MiniJava ist sehr primitiv.•
Die Programmiersprahe Java bietet noh eine Fülle von Hilfsmitteln an, die das Programmieren erleihtern sollen.Insbesondere gibt es
•
viele weitere Datenstrukturen (niht nur int) und•
viele weitere Kontrollstrukturen.... kommt später in der Vorlesung !!
Syntax (Lehre vom Satzbau):
•
formale Beshreibung des Aufbaus der Worte und Sätze, diezu einer Sprahe gehören;
•
im Falle einer Programmier-Sprahe Festlegung, wie Programme aussehen müssen.•
Wörterbüher;•
Rehtshreibregeln, Trennungsregeln, Grammatikregeln;•
Ausnahme-Listen;•
Sprah-Gefühl.•
Listen von Shlüsselworten wie if, int, else, while ...•
Regeln, wie einzelne Worte (Tokens) z.B. Namen gebildetwerden.
Frage:
Ist x10 ein zulässiger Name für eine Variable?
oder _ab$ oder A#B oder 0A?B ...
•
Grammatikregeln, die angeben, wie gröÿere Komponenten aus kleineren aufgebaut werden.Frage:
Ist ein while-Statement im else-Teil erlaubt?
•
Kontextbedingungen.Beispiel:
Eine Variable muss erst deklariert sein, bevor sie verwendet
wird.
== ⇒
formalisierter als natürlihe Sprahe== ⇒
besser für mashinelle Verarbeitung geeignet•
Ein Satz einer (natürlihen) Sprahe verfügt zusätzlih über eine Bedeutung, d.h. teilt einem Hörer/Leser einen Sahverhalt mit(
↑
Information)•
Ein Satz einer Programmiersprahe, d.h. ein Programm verfügt ebenfalls über eine Bedeutung ...•
alle möglihen Ausführungen der beshriebenen Berehnung(
↑
operationelle Semantik); oder•
die denierte Abbildung der Eingaben auf die Ausgaben(
↑
denotationelle Semantik).Ahtung!
Ist ein Programm syntaktish korrekt, heiÿt das noh lange niht,
dass es auh das rihtige tut, d.h. semantish korrekt ist !!!
•
alle möglihen Ausführungen der beshriebenen Berehnung(
↑
operationelle Semantik); oder•
die denierte Abbildung der Eingaben auf die Ausgaben(
↑
denotationelle Semantik).Ahtung!
Ist ein Programm syntaktish korrekt, heiÿt das noh lange niht,
dass es auh das rihtige tut, d.h. semantish korrekt ist !!!
•
int→
Bezeihner für Basis-Typen;•
if, else, while→
Shlüsselwörter aus Programm-Konstrukten;•
(,), ",', {,}, ,,;→
Sonderzeihen.Shritt 1: Angabe der erlaubten Zeihen:
letter
:: =
$|
_|
a| . . . |
z|
A| . . . |
Zdigit
:: =
0| . . . |
9•
•
•
Shritt 1: Angabe der erlaubten Zeihen:
letter
:: =
$|
_|
a| . . . |
z|
A| . . . |
Zdigit
:: =
0| . . . |
9•
letter und digit bezeihnen Zeihenklassen, d.h. Mengen von Zeihen, die gleih behandelt werden.•
Das Symbol|
trennt zulässige Alternativen.•
Das Symbol. . .
repräsentiert die Faulheit, alle Alternativen wirklih aufzuzählen.name
:: =
letter ( letter|
digit )*•
Erst kommt ein Zeihen der Klasse letter, dann eine (eventuellauh leere) Folge von Zeihen entweder aus letter oder aus digit.
•
Der Operator * bedeutet beliebig ofte Wiederholung (weglassen ist 0-malige Wiederholung).•
Der Operator * ist ein Postx-Operator. Das heiÿt, er steht hinter seinem Argument.•
_178Das_ist_kein_Name
x
_
$Password$
... sind legale Namen.
•
5ABC!Hallo!
x'
-178
... sind keine legalen Namen.
Ahtung:
Reservierte Wörter sind als Namen verboten !!!
•
5ABC!Hallo!
x'
-178
... sind keine legalen Namen.
Ahtung:
Reservierte Wörter sind als Namen verboten !!!
Werte, die direkt im Programm stehen, heiÿen Konstanten.
Ganze nihtnegative Zahlen bestehen aus einer nihtleeren Folge von
Ziern:
number
:: =
digit digit*•
Werte, die direkt im Programm stehen, heiÿen Konstanten.
Ganze nihtnegative Zahlen bestehen aus einer nihtleeren Folge von
Ziern:
number
:: =
digit digit*•
Wie sähe die Regel aus, wenn wir führende Nullen verbietenwollen?
•
1712490
42
0
00070
... sind alles legale int-Konstanten.
•
"Hello World!"0.5e+128
... sind keine int-Konstanten.
|
(Alternative)* (Iteration)
(Konkatenation) sowie
? (Option)
... aufgebaut sind, heiÿen reguläre Ausdrüke a
(
↑
Automatentheorie).Der Postx-Operator ? besagt, dass das Argument eventuell auh
fehlen darf, d.h. einmal oder keinmal vorkommt.
a
Gelegentlih sind auh
ǫ
, d.h. das leere Wort sowie∅
, d.h. die leere Mengezugelassen.
Worten aus.
•
( letter letter )*alle Wörter gerader Länge (über a,...,z,A,...,Z);
•
letter* test letter*alle Wörter, die das Teilwort test enthalten;
•
_ digit* 17alle Wörter, die mit _ anfangen, dann eine beliebige Folge von
Ziern aufweisen, die mit 17 aufhört;
• exp ::= ( e | E )(
+|
-)? digit digit
*float ::= digit digit
*exp |
digit
*(digit . | . digit) digit
*exp?
alle Gleitkomma-Zahlen ...
•
reservierten Wörtern,•
Namen,•
KonstantenIgnorierung von
•
White Spae,•
Kommentaren... erfolgt in einer ersten Phase (
↑
Sanner)== ⇒
Input wird mit regulären Ausdrüken verglihen und dabei inWörter (Tokens) aufgeteilt.
In einer zweiten Phase wird die Struktur des Programms analysiert
(
↑
Parser).Programme sind hierarhish aus Komponenten aufgebaut. Für jede
Komponente geben wir Regeln an, wie sie aus anderen Komponenten
zusammengesetzt sein können.
program
:: =
del* stmt*del
:: =
type name ( , name )* ;type
:: =
int•
Ein Programm besteht aus einer Folge von Deklarationen, gefolgt von einer Folge von Statements.•
Eine Deklaration gibt den Typ an, hier: int, gefolgt von einer Komma-separierten Liste von Variablen-Namen.Programme sind hierarhish aus Komponenten aufgebaut. Für jede
Komponente geben wir Regeln an, wie sie aus anderen Komponenten
zusammengesetzt sein können.
program
:: =
del* stmt*del
:: =
type name ( , name )* ;type
:: =
int•
Ein Programm besteht aus einer Folge von Deklarationen, gefolgt von einer Folge von Statements.•
Eine Deklaration gibt den Typ an, hier: int, gefolgt von einer Komma-separierten Liste von Variablen-Namen.stmt
:: =
;|
{ stmt* }|
name = expr;
|
name = read();|
write( expr );|
if ( ond ) stmt
|
if ( ond ) stmt else stmt
|
while ( ond ) stmt
•
Ein Statement ist entweder leer (d.h. gleih ;) oder einegeklammerte Folge von Statements;
•
oder eine Zuweisung, eine Lese- oder Shreib-Operation;•
eine (einseitige oder zweiseitige) bedingte Verzweigung;•
oder eine Shleife.expr
:: =
number|
name|
( expr )|
unop expr
|
expr binop exprunop
:: =
-binop
:: =
-|
+|
*|
/|
%•
Ein Ausdruk ist eine Konstante, eine Variable oder eingeklammerter Ausdruk
•
oder ein unärer Operator, angewandt auf einen Ausdruk,•
oder ein binärer Operator, angewand auf zweiArgument-Ausdrüke.
•
Einziger unärer Operator ist (bisher) die Negation.•
Möglihe binäre Operatoren sind Addition, Subtraktion, Multiplikation, (ganz-zahlige) Division und Modulo.ond
:: =
true|
false|
( ond )|
expr omp expr
|
bunop ond
|
ond bbinop ondomp
:: =
==|
!=|
<=|
<|
>=|
>bunop
:: =
!bbinop
:: =
&&|
||•
Bedingungen untersheiden sih dadurh von Ausdrüken, dass ihr Wert niht vom Typ int ist sondern true oder false (einWahrheitswert vom Typ boolean).
•
Bedingungen sind darum Konstanten, Vergleihe•
oder logishe Verknüpfungen anderer Bedingungen.int x;
x = read();
if (x > 0)
write(1);
else
write(0);
Die hierarhishe Untergliederung von Programm-Bestandteilen
veranshaulihen wir durh Syntax-Bäume:
expr
number name
expr
comp cond
0 x >
number expr stmt
number expr stmt
) ;
write ( 1 write ( 0 ) ;
Blätter: Wörter/Tokens
innere Knoten: Namen von Programm-Bestandteilen
program
stmt
>
cond
comp
if ( x name
expr
number expr stmt
write ( 0 ) ; 0
number expr
number expr stmt
) ;
write ( 1 else
) name
stmt
x = read ( ) ; decl
; name
x type
int
•
Die vorgestellte Methode der Beshreibung von Syntax heiÿt EBNF-Notation (Extended Bakus Naur Form Notation).•
Ein anderer Name dafür ist erweiterte kontextfreie Grammatik(
↑
Linguistik, Automatentheorie).•
Linke Seiten von Regeln heiÿen auh Niht-Terminale.•
Tokens heiÿen auh Terminale.Noam Chomsky,
MIT
Turing Award
(Ernder von Fortran)
Peter Naur,
Turing Award
(Ernder von Algol60)
•
Die regulären Ausdrüke auf den rehten Regelseiten können sowohl Terminale wie Niht-Terminale enthalten.•
Deshalb sind kontextfreie Grammatiken mähtiger als reguläre Ausdrüke.Beispiel:
L = {ǫ,
ab,
aabb,
aaabbb, . . .}
lässt sih mithilfe einer Grammatik beshreiben:
A
:: =
( a A b )?a a a
A
b b b
A A A
Für
L
gibt es aber keinen regulären Ausdruk!!! (↑
Automatentheorie)In welher Weise die Operationen eines Programms naheinander
ausgeführt werden, lässt sih anshaulih mithilfe von
Kontrolluss-Diagrammen darstellen.
Ingredienzien:
Start Stop
Endknoten Startknoten
x = read(); write(y); x = x - y;
Eingabe Ausgabe Zuweisung
no yes x < y
Kante Zusammenlauf
bedingte Verzweigung
int x, y;
x = read();
y = read();
while (x != y)
if (x < y)
y = y - x;
else
x = x - y;
write(x);
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
•
Die Ausführung des Programms entspriht einem Pfad durhdas Kontrolluss-Diagramm vom Startknoten zum Endknoten.
•
Die Deklarationen von Variablen muss man sih am Startknoten vorstellen.•
Die auf dem Pfad liegenden Knoten (auÿer dem Start- undEndknoten) sind die dabei auszuführenden Operationen bzw.
auszuwertenden Bedingungen.
•
Um den Nahfolger an einem Verzweigungsknoten zubestimmen, muss die Bedingung für die aktuellen Werte der
Variablen ausgewertet werden.
== ⇒
operationelle SemantikStart
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 18, y == 24
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 18, y == 24
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 18, y == 24
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 18, y == 6
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 18, y == 6
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 12, y == 6
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 12, y == 6
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 6, y == 6
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 6, y == 6
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
x == 6, y == 6
Start
no yes
Stop
yes write(x); no
x = read();
y = read();
y=y−x;
x=x−y;
x != y
x < y
•
Zu jedem MiniJava-Programm lässt sih ein Kontrolluss-Diagramm konstruieren;•
die umgekehrte Rihtung gilt zwar ebenfalls, liegt aber niht soauf der Hand.
Stop Start
no yes
no yes yes
no yes yes
Um komfortabel programmieren zu können, brauhen wir
•
mehr Datenstrukturen;•
mehr Kontrollstrukturen.•
Auÿer int, stellt Java weitere Basistypen zur Verfügung.•
Zu jedem Basistyp gibt es eine Menge mögliher Werte.•
Jeder Wert eines Basistyps benötigt die gleihe Menge Platz,um ihn im Rehner zu repräsentieren.
•
Der Platz wird in Bit gemessen.(Wie viele Werte kann man mit
n
Bit darstellen?)Typ Platz kleinster Wert gröÿter Wert
byte 8
−128 127
short 16
−32 768 32 767
int 32
−2 147 483 648 2 147 483 647
long 64
−9 223 372 036 854 775 808 9 223 372 036 854 775 807
Die Benutzung kleinerer Typen wie byte oder short spart Platz.
Ahtung: Java warnt niht vor Überlauf/Unterlauf !!
Typ Platz kleinster Wert gröÿter Wert
byte 8
−128 127
short 16
−32 768 32 767
int 32
−2 147 483 648 2 147 483 647
long 64
−9 223 372 036 854 775 808 9 223 372 036 854 775 807
Die Benutzung kleinerer Typen wie byte oder short spart Platz.
Ahtung: Java warnt niht vor Überlauf/Unterlauf !!
int x = 2147483647; // grösstes int
x = x+1;
write(x);
... liefert -2147483648 ...
•
In realem Java kann man bei der Deklaration einer Variablen ihr direkt einen ersten Wert zuweisen (Initialisierung).•
Man kann sie sogar (statt am Anfang des Programms) erst ander Stelle deklarieren, an der man sie das erste Mal brauht!
Typ Platz kleinster Wert gröÿter Wert
float 32 a. -3.4e+38 a. 3.4e+38 7 signikante Stellen
double 64 a. -1.7e+308 a. 1.7e+308 15 signikante Stellen
•
Überlauf/Unterlauf liefert die Werte Infinity bzw.-Infinity.
•
Für die Auswahl des geeigneten Typs sollte die gewünshteGenauigkeit des Ergebnisses berüksihtigt werden.
•
Gleitkomma-Konstanten im Programm werden als double aufgefasst.•
Zur Untersheidung kann man an die Zahl f (oder F) bzw. dTyp Platz Werte
boolean 1 true, false
har 16 alle Uniode-Zeihen
Uniode ist ein Zeihensatz, der alle irgendwo auf der Welt gängigen
Alphabete umfasst, also zum Beispiel:
•
die Zeihen unserer Tastatur (inklusive Umlaute);•
die hinesishen Shriftzeihen;•
die ägyptishen Hieroglyphen ...har-Konstanten shreibt man mit Hohkommas: 'A', ';', '\n'.
•
Die Operatoren +, -, *, / und % gibt es für jeden deraufgelisteten Zahltypen.
•
Werden sie auf ein Paar von Argumenten vershiedenen Typsangewendet, wird automatish vorher der speziellere in den
allgemeineren umgewandelt (impliziter Type Cast) ...
Gleitkomma-Zahlen
ganze Zahlen
float
byte
long
int
short
har
short xs = 1;
int x = 999999999;
write(x + xs);
... liefert den int-Wert 1000000000 ...
float xs = 1.0f;
int x = 999999999;
write(x + xs);
... liefert den float-Wert 1.0E9 ...
... vorausgesetzt, write() kann Gleitkomma-Zahlen ausgeben.
short xs = 1;
int x = 999999999;
write(x + xs);
... liefert den int-Wert 1000000000 ...
float xs = 1.0f;
int x = 999999999;
write(x + xs);
... liefert den float-Wert 1.0E9 ...
... vorausgesetzt, write() kann Gleitkomma-Zahlen ausgeben.
•
Das Ergebnis einer Operation auf float kann aus dem Bereihvon float herausführen. Dann ergibt sih der Wert Infinity
oder -Infinity.
Das gleihe gilt für double.
•
Das Ergebnis einer Operation auf Basistypen, die in int enthalten sind (auÿer har), liefern ein int.•
Wird das Ergebnis einer Variablen zugewiesen, sollte deren Typ dies zulassen.Der Datentyp String für Wörter ist kein Basistyp, sondern eine
Klasse (dazu kommen wir später)
Hier behandeln wir nur drei Eigenshaften:
•
Werte vom Typ String haben die Form "Hello World!";•
Man kann Wörter in Variablen vom Typ String abspeihern.•
Man kann Wörter mithilfe des Operators + konkatenieren.String s0 = "";
String s1 = "Hel";
String s2 = "lo Wo";
String s3 = "rld!";
write(s0 + s1 + s2 + s3);
... shreibt Hello World! auf die Ausgabe.
•
Jeder Wert in Java hat eine Darstellung als String.•
Wird der Operator + auf einen Wert vom Typ String undeinen anderen Wert
x
angewendet, wirdx
automatish in seineString-Darstellung konvertiert ...
== ⇒
... liefert einfahe Methode, um float oder doubleauszugeben !!!
Beispiel:
double x = -0.55e13;
write("Eine Gleitkomma-Zahl: "+x);
... shreibt Eine Gleitkomma-Zahl: -0.55E13 auf die Ausgabe.
Oft müssen viele Werte gleihen Typs gespeihert werden.
Idee:
•
Lege sie konsekutiv ab!•
Greife auf einzelne Werte über ihren Index zu!3 -2 0 1
17 9
0 1 2 3 4 5
Index:
Feld:
int[℄ a; // Deklaration
int n = read();
a = new int[n℄;
// Anlegen des Felds
int i = 0;
while (i < n) {
a[i℄ = read();
i = i+1;
}
•
type [℄ name ; deklariert eine Variable für ein Feld (array),dessen Elemente vom Typ type sind.
•
Alternative Shreibweise:type name [℄;
•
Das Kommando new legt ein Feld einer gegebenen Gröÿe an undliefert einen Verweis darauf zurük:
a a
a = new int[6℄;
•
Der Wert einer Feld-Variable ist also ein Verweis.•
int[℄ b = a; kopiert den Verweis der Variablen a in dieVariable b:
a
b a
int[℄ b = a;
•
Die Elemente eines Felds sind von 0 an durhnumeriert.•
Die Anzahl der Elemente des Felds name ist name.length.•
Auf dasi
-te Element des Felds name greift man mittelsname[i℄ zu.
•
Bei jedem Zugri wird überprüft, ob der Index erlaubt ist, d.h.im Intervall
{0, . . . ,
name.length-1}
liegt.•
Liegt der Index auÿerhalb des Intervalls, wird dieArrayIndexOutofBou nd sEx ep ti on ausgelöst (
↑
Exeptions).•
Java unterstützt direkt nur ein-dimensionale Felder.•
Ein zwei-dimensionales Feld ist ein Feld von Feldern ...a a a
a = new int[5℄[6℄;
Typishe Form der Iteration über Felder:
•
Initialisierung des Laundex;•
while-Shleife mit Eintrittsbedingung für den Rumpf;•
Modizierung des Laundex am Ende des Rumpfs.int result = a[0℄;
int i = 1; // Initialisierung
while (i < a.length) {
if (a[i℄ < result)
result = a[i℄;
i = i+1; // Modifizierung
}
write(result);
int result = a[0℄;
for (int i = 1; i < a.length; ++i)
if (a[i℄ < result)
result = a[i℄;
write(result);
for ( init; ond; modify ) stmt
... entspriht:
{ init ; while ( ond ) { stmt modify ;} }
... wobei ++i äquivalent ist zu i = i+1 .
•
Die Zuweisung x = x-1 ist in Wahrheit ein Ausdruk.•
Der Wert ist der Wert der rehten Seite.•
Die Modizierung der Variable x erfolgt als Seiteneekt.•
Der Semikolon ; hinter einem Ausdruk wirft nur den Wertweg.
== ⇒
... fatal für Fehler in Bedingungen ...boolean x = false;
if (x = true)
write("Sorry! This must be an error ...");
•
Die Operatoranwendungen ++x und x++ inkrementieren beide den Wert der Variablen x.•
++x tut das, bevor der Wert des Ausdruks ermittelt wird(Pre-Inrement).
•
x++ tut das, nahdem der Wert ermittelt wurde(Post-Inrement).
•
a[x++℄ = 7; entspriht:a[x℄ = 7;
x = x+1;
•
a[++x℄ = 7; entspriht:x = x+1;
a[x℄ = 7;
•
Teilprobleme separat lösen; und dann•
die Lösung mehrfah verwenden;== ⇒
Funktionen, ProzedurenBeispiel: Einlesen eines Felds
publi stati int[℄ readArray(int n) {
// n = Anzahl der zu lesenden Elemente
int[℄ a = new int[n℄; // Anlegen des Felds
for (int i = 0; i < n; ++i) {
a[i℄ = read();
}
return a;
•
Die erste Zeile ist der Header der Funktion.•
publi sagt, wo die Funktion verwendet werden darf(
↑
kommt später)•
stati kommt ebenfalls später.•
int[℄ gibt den Typ des Rükgabe-Werts an.•
readArray ist der Name, mit dem die Funktion aufgerufenwird.
•
Dann folgt (in runden Klammern und komma-separiert) die Liste der formalen Parameter, hier: (int n).•
Der Rumpf der Funktion steht in geshwungenen Klammern.•
return expr beendet die Ausführung der Funktion und liefertden Wert von expr zurük.
•
Die Variablen, die innerhalb eines Bloks angelegt werden, d.h.innerhalb von { und }, sind nur innerhalb dieses Bloks
sihtbar, d.h. benutzbar (lokale Variablen).
•
Der Rumpf einer Funktion ist ein Blok.•
Die formalen Parameter können auh als lokale Variablenaufgefasst werden.
•
Bei dem Aufruf readArray(7) erhält der formale Parameter n den Wert 7.publi stati int min (int[℄ a) {
int result = a[0℄;
for (int i = 1; i < a.length; ++i) {
if (a[i℄ < result)
result = a[i℄;
}
return result;
}
publi lass Min extends MiniJava {
publi stati int[℄ readArray (int n) { ... }
publi stati int min (int[℄ a) { ... }
// Jetzt kommt das Hauptprogramm
publi stati void main (String[℄ args) {
int n = read();
int[℄ a = readArray(n);
int result = min(a);
write(result);
} // end of main()
} // end of lass Min
•
Manhe Funktionen, deren Ergebnistyp void ist, geben gar keine Werte zurük im Beispiel: write() und main(). DieseFunktionen heiÿen Prozeduren.
•
Das Hauptprogramm hat immer als Parameter ein Feld args von String-Elementen.•
In diesem Argument-Feld werden dem ProgrammKommandozeilen-Argumente verfügbar gemaht.
publi lass Test extends MiniJava {
publi stati void main (String [℄ args) {
write(args[0℄+arg s[ 1℄) ;
}
} // end of lass Test
java Test "Hel" "lo World!"
... die Ausgabe: Hello World!
erweitern/modizieren wir die Kontrolluss-Diagramme:
x = f(7,z); return 42;
f(x,y)
Funktionsaufruf Endknoten Startknoten
der Funktion
f
•
Für jede Funktion wird ein eigenes Teildiagramm erstellt.•
Ein Aufrufknoten repäsentiert eine Teilberehnung der aufgerufenen Funktion.result = a[0];
i = 1;
i = i+1;
a[i]<result
result = a[i];
i<a.length
no yes
no yes
min(a)
return result;
return a;
return;
n = read();
main(args)
result = min(a);
a = readArray(n);
min(a)
return result;
write(result);
readArray(n)
min(a)
return result;
n = read();
return;
return a;
readArray(n)
result = min(a);
a = readArray(n);
main(args)
write(result);
Aufruf
Rükkehr
min(a)
return result;
n = read();
return;
result = min(a);
a = readArray(n);
return a;
readArray(n) main(args)
write(result);
Rükkehr
Aufruf
Gegeben: eine Folge von ganzen Zahlen.
Gesuht: die zugehörige aufsteigend sortierte Folge.
•
•
•
Gegeben: eine Folge von ganzen Zahlen.
Gesuht: die zugehörige aufsteigend sortierte Folge.
Idee:
•
speihere die Folge in einem Feld ab;•
lege ein weiteres Feld an;•
füge der Reihe nah jedes Element des ersten Felds an derrihtigen Stelle in das zweite Feld ein!
== ⇒
Sortieren durh Einfügen ...int n = a.length;
int[℄ b = new int[n℄;
for (int i = 0; i < n; ++i)
insert (b, a[i℄, i);
// b = Feld, in das eingefügt wird
// a[i℄ = einzufügendes Element
// i = Anzahl von Elementen in b
return b;
} // end of sort ()
Teilproblem: Wie fügt man ein ???
17
17
3 17
3 17
17 3
-2
17 3
-2
3
-2 9 17
3 9 17 -2
3 9 17 -2 0
3 9 17 -2 0
17 9
-2 0 1 3
17 9
-2 0 1 3
17 9
-2 0 1 3 7
-2 0 1 3 7 9 17 42
7 9 17 42 -2 0 1 3
-2 0 1 3 5 7 9 17 42
int j = loate (b,x,i);
// findet die Einfügestelle j für x in b
shift (b,j,i);
// vershiebt in b die Elemente b[j℄,...,b[i-1℄
// nah rehts
b[j℄ = x;
}
Neue Teilprobleme:
•
Wie ndet man die Einfügestelle?•
Wie vershiebt man nah rehts?int j = 0;
while (j < i && x > b[j℄) ++j;
return j;
}
publi stati void shift (int[℄ b, int j, int i) {
for (int k = i-1; k >= j; --k)
b[k+1℄ = b[k℄;
}
•
Warum läuft die Iteration in shift() von i-1 abwärts nah j ?•
Das zweite Argument des Operators && wird nur ausgewertet, sofern das erste true ergibt (Kurzshluss-Auswertung!). Sonstwürde hier auf eine uninitialisierte Variable zugegrien !!!
•
Das Feld b ist (ursprünglih) eine lokale Variable von sort().•
Lokale Variablen sind nur im eigenen Funktionsrumpf sihtbar, niht in den aufgerufenen Funktionen !•
Damit die aufgerufenen Hilfsfunktionen auf b zugreifen können, muss b explizit als Parameter übergeben werden !Ahtung:
Das Feld wird niht kopiert. Das Argument ist der Wert der
Variablen b, also nur eine Referenz !
•
Deshalb benötigen weder insert(), noh shift() einenseparaten Rükgabewert ...
•
Weil das Problem so klein ist, würde eine erfahreneProgrammiererin hier keine Unterprogramme benutzen ...
int[℄ b = new int[a.length℄;
for (int i = 0; i < a.length; ++i) {
// begin of insert
int j = 0;
while (j < i && a[i℄ > b[j℄) ++j;
// end of loate
for (int k = i-1; k >= j; --k)
b[k+1℄ = b[k℄;
// end of shift
b[j℄ = a[i℄;
// end of insert
}
return b;
} // end of sort
•
Die Anzahl der ausgeführten Operationen wähst quadratish in der Gröÿe des Felds a ??•
Gükliherweise gibt es Sortier-Verfahren, die eine bessere Laufzeit haben (↑
Algorithmen und Datenstrukturen).Nehmen wir an, wir wollen herausnden, ob das Element 7 in
unserem Feld a enthalten ist.
Naives Vorgehen:
•
Wir vergleihen 7 der Reihe nah mit den Elementen a[0℄,a[1℄, usw.
•
Finden wir ein i mit a[i℄ == 7, geben wir i aus.•
Andernfalls geben wir -1 aus: Sorry, gibt's leider niht !int i = 0;
while (i < a.length && a[i℄ != x)
++i;
if (i == a.length)
return -1;
else
return i;
}
17 3 -2 9 0 1 7 42 5
17 3 -2 9 0 1 7 42 5
17 3 -2 9 0 1 7 42 5
17 3 -2 9 0 1 7 42 5
17 3 -2 9 0 1 7 42 5
17 3 -2 9 0 1 7 42 5
17 3 -2 9 0 1 7 42 5
•
Im Beispiel benötigen wir 7 Vergleihe.•
Im shlimmsten Fall benötigen wir bei einem Feld der Längen
sogarn
Vergleihe ??•
Kommt 7 tatsählih im Feld vor, benötigen wir selbst imDurhshnitt
(n + 1)/2
viele Vergleihe ??Geht das niht besser ???
•
Sortiere das Feld.•
Vergleihe 7 mit dem Wert, der in der Mitte steht.•
Liegt Gleihheit vor, sind wir fertig.•
Ist 7 kleiner, brauhen wir nur noh links weitersuhen.•
Ist 7 gröÿer, brauhen wir nur noh rehts weiter suhen.== ⇒
binäre Suhe ...0 1 3 5 7 9 17 42 -2
0 1 3 5 7 9 17 42 -2
0 1 3 5 7 9 17 42 -2
0 1 3 5 7
-2 9 17 42
0 1 3 5 7 9 17 42 -2