Ja, herzlich willkommen zur vierten Vorlesung von SE1. Ich
glaube, diesmal sind wir mit dem Livestream auch online.
Das hört sich gut an. Ich mache heute anfangs keine Sturesi-Umfrage,
um zu erfassen, wie viele Leute da sind.
Sondern heute gibt es die Fragen ganz zum Schluss,
nur dass ihr schon mal ein bisschen wisst, was euch strukturell erwartet.
Ich will heute ein paar imperative Grundkonzepte noch einführen.
Das ist auf eine Art
relativ trocken
Fast schon kontextfrei. Ich werde was über Ausdrücke erzählen,
in imperativen Programmiersprachen, insbesondere in Java. Da sind die
Basistypen involviert, da sind die literale involviert, Operatoren,
all das Zeug, das müssen wir alles mal durchnehmen.
Ich glaube aber, dass das zum einen für die Leute,
die noch nicht programmieren können, nachvollziehbar ist.
Auf der anderen Seite glaube ich aber auch, dass das,
was ich jetzt hier erzähle, für viele Leute überraschend ist,
die meinen schon programmieren zu können.
Aber das müssen wir dann vielleicht am Ende sehen.
Okay, eingangs möchte ich heute was sagen zu Variablen
nochmal und zu Zuweisung
Ist ja auch was sehr Elementares in der imperativen Programmierung.
Das Variablen, Abstraktionen sind von Speichern und Speicherszellen
und dass sie ihre Belegung auch verändern können.
Okay, diese Folie habe ich schon mal gezeigt,
an dem ganz einfachen Beispiel Girokonto.
Wir haben hier so die Klassendefinition und wir sehen die Bestandteile
eines einer Klassendefinition, hier eine Exemplarvariable und eine Methode.
Also eine sehr kleine, einfache Klasse.
Die habe ich auch nochmal gleich in Blue Jay
Ich will nur auch nochmal ganz kurz darauf ansprechen,
dass wir generell bei einer Variable sagen,
dass man einen Typ angeben muss und einen Namen.
Das habt ihr jetzt schon mehrfach von uns nachgefragt bekommen,
auch in den Übungen. Wir pochen da sehr drauf.
Was ist denn eine Variable? Also, eine Variable,
einen Namen und ein Typ, zumindest in Java,
muss sie immer einen Typ haben.
Es gibt Programmiersprachen, da muss man keinen Typ mit angeben.
Und während der Ausführung eines Programms hat dann so eine Variable irgendwie
eine Belegung. Das heißt, sie hält einen Wert.
Wir kennen zwischen drei Arten von Variablen, nämlich Exemplarvariablen.
Das ist so eine Exemplarvariable hier
Jedes Exemplar dieser Klasse hält so einen Satz von Exemplarvariablen,
beziehungsweise dann ein Exemplar hat dann Felder.
Methoden können formale Parameter haben. Das sehen wir hier.
Betrag ist ein formaler Parameter, der Methode einzahlen. Und lokale Variablen,
die als Hilfsvariablen in den Rümpfen von Methoden vorkommen können.
Hier ist ein Beispiel, eine lokale Variable in Neuer Saldo.
Dann wird hier irgendwas berechnet,
Saldo plus Betrag und das wird der lokalen Variablen zugewiesen und
erst zum Schluss wird hier der Exemplarvariablen dieser neu berechnete
Wert zugewiesen
Das ist hier explizit ein bisschen auseinandergezogen. Und man sieht
hier nochmal ganz deutlich, das ist eine Exemplare.
Ja, das ist ein formaler Parameter. Das ist eine
lokale Variante. Das sind alles Arten von Variablen.
Und die werden wir uns etwas genauer ansehen nochmal.
Aber erstmal ein bisschen Blue Jay. Genau dieses Projekt.
Genau diese Klasse, beziehungsweise nicht genau diese Klasse,
sondern wie ihr hier seht, zusätzlich noch die Operation.
Die Methode gibt Saldo. Hier ist Miki Psaldo. Das habt ihr auch schon gesehen,
dass es eine sondierende Methode, mit der ich den Saldo abfragen kann,
mit der ein Klient dieser Klasse den Saldo abfragen kann.
So, jetzt kann ich hier mal was demonstrieren,
was die Initialisierung dieser Variablen angeht. Also,
wir haben gesagt, wenn mich jetzt so ein Konto erzeuge,
dann soll das ja einen Anfangssaldo bekommen.
Man sieht hier dieser Konstruktor ist, ach ja,
hier ist tatsächlich auch noch ein Konstruktor,
das ist auch noch anders als auf der Folie.
Hier ist ein Konstruktor, der ein frisch erzeugtes Konto in den richtigen Ausgangszustand setzt.
Man kann also tatsächlich hier einen Anfangssaldo angeben. Was ich
jetzt mal mache, ich setze hier mal einen Haltepunkt rein.
Und jetzt erzeuge ich ein Exemplar dieser Klasse und sage Anfangssaldo von 10.
Und jetzt wird der Debugger hier hoffentlich aufspringen und mir anzeigen,
wie der Stand der Dinge ist.
Wir sind jetzt im Konstruktor. Das heißt, das Exemplar ist
schon erzeugt. Das ist ja das, was viele überrascht.
Aber es ist tatsächlich so, das Exemplar ist schon da.
Und der Konstruktor erzeugt das Exemplar nicht, sondern er initialisiert ist.
So, das heißt, wir sind jetzt hier gerade an
der gelb markierten Zeile im Konstruktor.
Und diese Zeile ist noch nicht ausgeführt. Was wir sehen,
ist hier Instanzvariablen. Das ist der andere Name für Exemplarvariablen
. In Blue Jay haben die das halt Instanzvariablen genannt.
Unterstrich Saldo hat jetzt hier den Wert Null
Das ist interessant. Das heißt, diese Variable,
dieser Exemplar war ja, der hat schon eine Belegung.
Nämlich null. Obwohl ich ja gerade hier,
und das ist die andere Variable, die im Mitreihen spielt,
das hier ist ein formaler Parameter.
Und die werden diese formalen Parameter, werden genau wie lokale Variablen,
als in diesem scheinen Fenster hier angezeigt, lokale Variable.
Tatsächlich sind lokale Variablen und formale Parameter in Java ziemlich gleich.
In der Benutzung. Man kann denen sogar was zuweisen.
Ich könnte tatsächlich jetzt hier auch dieser Variablen etwas zuweisen.
Das geht in Java. Das ist nicht sehr sinnvoll,
aber man kann das machen
Aber ich habe ja jetzt, als ich den Konstrukt da aufgerufen habe,
musste ich als Klient ja einen aktuellen Parameter angeben.
Das heißt, die ist tatsächlich ein Wert übergeben worden.
Und dieser Wert steht jetzt tatsächlich in dem formalen Parameter.
So, und man sieht aber jetzt erstmal diese Exemplarvariable,
ist initialisiert mit Null. Das ist der Standardwert für Int-Variablen,
für Int-Felder. Und hier habe ich jetzt die Möglichkeit,
diese Zeile einmal auszufinden. Wenn ich das jetzt ausführe,
diese eine Zeile, dann ist tatsächlich hier Anfang Saldo dem
Saldo zugewiesen worden und entsprechend hat die Exemplare ja aber jetzt den BR10.
So, und dann sage ich hier Fortsetzen,
dann habe ich mein neues Exemplar erzeugt und hier ist es.
Und das hat, wenn ich mir den Saldo geben lasse, den Saldo 10,
Jetzt kann ich an diesem Exemplar eine Methode aufrufen, zum Beispiel einzahlen.
Jetzt kann ich auch mal zeigen, an so einem Live-Objekt,
ich kann jetzt hier einen weiteren Haltepunkt reinsetzen,
dass wir auch nochmal den Zusammenhang sehen zwischen lokalen Variablen und formalen Parametern und Feldern.
Ich kann jetzt hier versuchen, in diese Methode einen Haltepunkt setzen.
Ich kann hier keinen Haltepunkt hinsetzen, keinerzeit Breakpoint,
weil hier keine Zuweisung steht oder überhaupt keine Anweisung,
sondern hier steht nur eine Deklaration.
Ich habe also hier eine lokale Variable deklariert, neuer Saldo,
also kann ich den Kontrollfluss frühestens hier anhalten.
Also hier tatsächlich jetzt, wenn die Methode aufgerufen wird,
ich kann das am lebenden Objekt machen,
Ich konnte hier einen Haltepunkt reinsetzen.
Das Objekt ist immer noch da. Jetzt kann ich hier
einzahlen, aufrufen. Und dann sage ich hier mal 20.
Das heißt, da müssten dann irgendwie 30 drauf sein am Ende.
So, jetzt sehe ich hier meine Exemplarvariable, die den Wert 10 hält.
Habe ich ja vorher mit dem Konstruktor da auf diesen Wert gesetzt.
Dann habe ich hier eine lokale Variable in Betrag.
Aber diese lokale Variable wieder aufpassen, ist eigentlich der formale Parameter.
Weil in diesem Fenster lokale Variablen und formale Parameter aufgeführt sind.
So, das heißt also, hier haben wir nur Betrag momentan.
Wo ist jetzt die lokale Variable?
Wir sind doch schon in dieser Zeile und die Deklaration war
doch davor
Und da sehen wir einen Effekt bei lokalen Variablen,
die kommen erst in die Existenz,
die werden erst sozusagen existent oder aktiv in der Programmausführung,
wenn tatsächlich denen ein Wert zugewiesen wurde.
Ihr müsst immer einer lokalen Variablen explizit einen Wert zuweisen,
bevor ihr ihn auslesen könnt.
Es ist also nicht so, dass jede Int-Variable eine Vorbelegung hat.
Felder, ja, lokale Variablen nicht. Das heißt,
an dieser Stelle, jetzt wenn ich diese Zeile ausführe,
wenn ich jetzt also einmal einen Schritt übermache,
dann wird tatsächlich hier diese neue Variable auftauchen.
Also die lokale Variable Neuer Saldo ist erst jetzt initialisiert,
also erst jetzt wurde Speicher dafür,
und der entsprechend auch belegt mit einem Wert.
Also Neuer Saldo hat jetzt den Wert 30 und unser Saldo ist immer noch zehn.
Jetzt wird diese Zuweisung ausgeführt. Das heißt, wenn ich
den Schritt jetzt mache, sollte unser Saldo 30 sein.
Und wenn ich das dann fortsetze, ist tatsächlich das Konto 30.
So, das einfach nur, dass ihr nochmal seht,
was der Zusammenhang ist zwischen diesen drei variablen Arten.
Hier nochmal auf den Folien. Jede variablen Art muss ich
erstmal deklarieren in Java. Typ und Bezeichner,
Exemplarvariablen in der Klassendefinition, formale Parameter in den Köpfen von Methoden,
lokale Variablen in den Rümpfen von Methoden
Haben wir schon mehrfach gesehen. Anfangsbelegung der variablen Arten ist,
bei einer Exemplarvariablen, da gibt es Startwerte,
die gucken wir uns zu später an.
Für die ganzen Typen, die Java schon vordefiniert hat,
gibt es immer klar definierte Werte. Also jedes Feld hat einen
klar definierten Wert. Auch wenn man im Konstruktor keine Initialisierung vornimmt.
Formale Parameter werden mit den Werten der aktuellen Parameter eines Aufrufs Berlin,
haben wir letzte Woche gehört, ich habe keine Wahl als Klient,
muss ich einen aktuellen Parameter angeben,
also kann ich als Dienstleister,
also innerhalb meines Rumpfes meiner Methode,
mit Sicherheit davon ausgehen,
dass meine formalen Parameter
irgendeine Belegung haben
Nur lokale Varianen sind ein bisschen anders. Die müssen halt
wirklich vom Programmierer explizit initialisiert werden. Wenn ihr versucht,
auf so eine Variable zuzugreifen, gibt es halt eine Fehlermeldung.
Bevor ihr etwas reingeschrieben habt. Okay. Das erste Mal
die Sache mit den variablen Arten, die wir in der objektorientierten Programmierung haben.
Zumindest in Java. Das Nächste, was ganz wichtig ist,
ist, dass so eine Variable ihre Belegung ändern kann.
Ich habe hier auf der Folie jetzt sowas wie Antwort.
Antwort ist möglicherweise vom Typ Int. Das kann ich meine Direkteingabe
hier demonstrieren. Also ich mache das hier mal ein bisschen breiter,
weil ich hier dann später noch ein bisschen mehr zeigen werde.
Also ich mache hier Int-I. Jetzt sagt er mir wieder,
hallo, die Variablen, die du hier jetzt so deklarierst,
die sind genauso wie Zustandsvariablen Hinweis.
Direkt werden automatisch behandelt, genau wie Objektattribute.
Also diese Variable hat jetzt schon den Wert Null.
Ja, I hat den Wert Null. Das ist quasi
wie bei Feldern. Es ist nicht wie bei lokalen Variablen
. So, und wenn ich jetzt sage,
I ist gleich 42, dann kann ich das hinschreiben.
Und dann hat I tatsächlich den Weg, den Wert 42.
Ich kann also wirklich den Wert hier in die Direkteingabe ja abfragen.
Ich kann sagen, was ist die Belegung der Variablen I
und das ist 42. Jetzt kann ich aber auch sagen,
Ist gleich I plus 2. Und dann hat I den Wert
44. Ganz elementar muss ich einfach immer noch mal deutlich sagen,
Variablen können ihre Belegung ändern. Punkt. Das muss einfach
sich ein bisschen einprägen, weil man sonst Gefahr läuft,
zu sehr auf den variablen Begriff in der Mathematik zu schielen.
Und da ist es halt ein bisschen anders. Gut,
hier noch mal angedeutet,
eine Variable kann man sich also wirklich vorstellen wie so ein Behälter,
wo irgendwas reinkommt und wo sich der Füllstand ändern kann.
Also ähnlich wie bei diesem Gewürzstreuer hier, in denen Pfeffer reinkommt.
Und der Pfeffer ist tatsächlich dann der Typ.
Also er kann nur Pfeffer rein, dann kann er nicht
in einen Pfefferstreuer sollte man nicht Salz auffüllen.
Das macht irgendwie nicht so viel Spaß dann. Gut.
Bei der Zuweisung gibt es noch so ein paar Dinge,
die man so als Begriffe bringen kann.
Also sowas hier wie ein Syntaxschema allgemein der Zuweisung.
Also es gibt immer eine linke Seite, dann den Zuweisungsoperator und die rechte Seite.
Und das muss man sich halt auch sehr genau angucken,
was da so passiert. Die rechte Seite ist,
sind meist arathmetische bulsche Ausdrücke, Vergleiche bezahlen oder Zeichenketten.
Zuweisungsoperator ist in Java, das einfache Gleichheitszeichen. Viel umstritten. Ist eine Wahl,
die die getroffen haben beim Design von Java,
weil sie sich an C und C Plus Bus angelehnt haben
und C und C Plus Plus sind zu Zeiten entstanden,
als Speicher knapp war.
Und da war es einfach so, wenn ich jetzt,
ähm, passt, was an die linke Seite reingespeichert werden soll.
Hier nochmal die Syntax in Java Level 1,
also auch nicht sehr sensationell.
Es gibt ein Nicht-Terminal-Assignment-Zuweisung. Identifier gleich Expression. Expression,
also ein Ausdruck, da kommen wir auch gleich noch zu
Ja, also zwischendurch in den Ausschlussbestrebungen gibt,
definieren die in bestimmten Domänen speziell angepasst sind,
also für den Versicherungsbereich oder für Stellwerke bei der Bahn oder
so domänenspezifische Sprachen, Domains, Specific Languages.
Wenn man die bauen will, muss man eigentlich einen Compiler bauen. So,
und dann sollte man ein bisschen mehr wissen und da gibt
es eben halt dann so Begriffe wie L-Wert und R-Wert und
das ist in Java relativ synonym mit linke Seite, rechte Seite.
L-Wert bezeichnet einer Variablen, links, das ist da, wo was reingegespeichert wird.
Und R-Wert ist irgendein Ausdruck, der einen Wert liefert.
Das ist auch schon deshalb wichtig zu erzählen,
weil man hier ein Beispiel sieht, A ist gleich A plus dreimal I.
Das ist also ein Ausdruck hier, dieser Teil,
das ist ein Ausdruck. Und wir sehen,
auf der rechten Seite steht das A und auf der
rechten Seite wird aus dem A irgendwas rausgelesen.
Da wird die Belegung von A vor dieser Zuweisung erst mal angeguckt,
was steht in A drin,
dann wird das irgendwie addiert mit dem Produkt aus 3 und
Und was immer da rauskommt,
das wird dann am Ende in die linke Seite reingespeichert.
Wäre viel intuitiver gewesen vielleicht, wenn man gesagt hätte,
ah, wir schreiben den Ausdruck nach links und haben dann so
einen Pfeil und dann das Ziel, wo es hingerät.
Aber es ist halt alles historisch. Also alles Unfälle,
die ihr hier ausbaden dürft. Programmiersprachen sind eigentlich ein einziger Unfall
. Naja, aber sie sind sehr nützlich. So,
auf der linken Seite ist jetzt A, das Ziel,
an dem was gespeichert wird, auf der rechten Seite,
das, wo was rausgelesen wird.
Also da steckt eine ganze Menge dahinter und das muss man
sich halt auch mal ein bisschen im Hinterkopf bewahren
Die Zuweisung in Java sieht eben so aus,
wenn ich zum Beispiel eine variable Antwort habe,
dann kann ich der 40 zuweisen.
Oder ich kann sagen, Antwort plus gleich zwei,
das ist dieser komische, kombinierte Zuweisungsapparator,
das ist Synonym zu Antwort, ist gleich Antwort plus zwei.
Kann man auch so schreiben. Ich finde das immer
relativ lästig. Das ist auch wieder so eine Schreibweise,
um zum einen weniger Speicherplatz wegzunehmen.
Zum anderen aber auch, weil man dann Registeroptimierungen machen kann.
Aber das ist noch am Rande wichtig, eigentlich auch eher für einen Compiler.
Dann haben wir hier was Ungewöhnliches. Korrekt ist gleich,
Antwort gleich, gleich 42. Hier werden also zwei Dinge verglichen,
irgendwie Antwort, anscheinend eine Variable vom Typ Int, vermutlich.
Hier steht ein Literal, 42, die werden verglichen.
Und wenn die gleich sind, dann ist das entweder True oder Falts.
Also wenn die gleich sind, ist es True und wenn
es nicht gleich ist, ist es Falts.
Und das scheint hier in einer Bullshen-Variablen gespeichert zu werden.
Sehen wir uns gleich alles nochmal ein bisschen genauer an.
Bullshen-Variablen sind ein bisschen was Komisches. Ganz wichtig,
es gibt eben halt diese Operatoren, man muss eben aufpassen,
dass das hier Gleichheit und Ungleichheit ist.
Also auch wenn ihr wissen wollt,
ob zwei Zahlen ungleich sind oder zwei Variablen,
dann könnt ihr mit diesem Ausrufezeichen gleich diese Ungleichheit abfragen.
Das ist halt
die Syntax in Java
Und das hat überhaupt nichts zu tun mit der Zuweisung.
Und das sind zwar wirklich verschiedene Dinge. Gleichheit, Testaufgleichheit
oder Ungleichheit und die Zuweisung. Völlig verschieden. Und das wird
halt gerne verwechselt. Da muss man ein bisschen aufpassen.
Also auch in den Übungen sehen wir das jede Woche immer wieder,
dass dann aus Versehen da, wo ein gleichgleich gedacht war,
ein Gleichsteht oder umgekehrt.
Gut. So, jetzt habe ich gesagt, Zuweisung,
zentraler Stellenwert. Auf der linken Seite steht das, wo
das Ergebnis hineinkommt. Aber das, was da hineinkommt,
das ist oft das Ergebnis irgendeiner Berechnung
Eigentlich ist das, was auf der rechten Seite einer Zuweisung
steht, ein Ausdruck und ein Ausdruck ist eine Verarbeitungsvorschrift.
Das heißt, was man da hinschreibt,
ist eine Anweisung an den Computer, also pass auf,
jetzt liest mal zuerst mal den Wert aus A aus,
dann addiere 42 drauf.
Das sind letztendlich Anweisungen, die der Compiler dann umsetzt in
Maschinensprache oder Bitecode oder was auch immer.
In so einem Ausdruck können jetzt verschiedene Dinge beteiligt sein,
damit dein Ergebnis zustande kommt. Es gibt Operatoren,
wie hieltet Plus-Symbol, das nennen wir einen Operator,
und wir haben hier Operanten
Das kennt ihr aus seiner Mathematik, es gibt Operatoren,
Operanten, das ist hier relativ ähnlich wie in der Mathematik.
Aber wir werden auf die Unterschiede zu sprechen kommen.
Wenn wir das uns jetzt hier ansehen, diese Situation,
diese Zuweisung hier, dann ist ja jetzt vielleicht dem einen
oder anderen intuitiv klar, welchen Typ A hat.
Aber so ganz klar ist das nicht. Hat mal jemand eine Idee,
welchen Typ A hier haben könnte in einem gültigen Java-Programm.
Int. Er sagt, Int ist ein gültiger Typ.
Das ist wohl richtig, weil ich kann hier ja irgendwie
ein Int, plus 42 kann ich ja rechnen,
das kann ich dann auch in Int abspeichern.
Weiterer Vorschlag
String ist auch möglich, sagt er. Also wenn tatsächlich A,
ein String ist, dann ist hier tatsächlich,
findet hier eine Verknüpfung statt, A plus 42.
Ich kann das sagen, an dieser Stelle tatsächlich das mal zeigen hier in Blue Jay.
Wenn ich einen String habe, String S,
dem beiße ich jetzt einfach mal die leere Zeichenkette zu.
Jetzt habe ich also, mein S ist leer.
Und wenn ich jetzt sage, S ist gleich Hallo,
natürlich muss ich dem jetzt wieder eine Zeichenkette richtig so zuweisen,
kann ich so zuweisen.
Damit ist enthält S, den String, hallo.
Und wenn ich jetzt schreibe, S ist gleich S plus 2,
dann ist hinterher der String tatsächlich Hallo 2. Das heißt,
es würden die Zeichenketten hallo und zwei aneinander gekettet.
Was da passiert ist, dass hier die 42 in
eine Zeichenkette umgewandelt wird. Das ist etwas komisches,
das werden wir uns gleich auch nochmal genauer angucken,
dass ab und zu in so Ausdrücken Dinge umgewandelt werden,
damit die miteinander zusammenpassen.
Aber welchen Typ könnte A noch haben?
Was sind noch weitere Vorschläge für einen Typ für A,
der gültig wäre
Ja. Bitte? Double. Er schlägt Double vor,
richtig. Könnte also tatsächlich eine Gleitkommazahl sein. Genauso möglich,
kann man auch so hinschreiben. Weitere Vorschläge. Ja.
Long gut, die ganzen Zahlenwerte könnten wir jetzt durchgehen,
aber das finde ich so spannend, ja.
Charakter. Charakter könnte es auch sein. Ja, tatsächlich.
Also man könnte sich tatsächlich vorstellen, dass A hier ein Charakter ist.
Dann ist dieser Ausdruck allerdings so nicht gültig.
Warum erläutere ich gleich? Ja, aber tatsächlich kann ich
sowas hinschreiben. Ich kann zum Beispiel sowas schreiben wie Char-CH,
soll mal den Wert A haben
So, deklariere ich hier einfach mal.
Meine Variable vom Typ Char, die ein großes A hält.
Und jetzt kann ich irgendwie schreiben, Char plus 42. Na
, sagen wir mal lieber, vielleicht plus zwei.
So, dieser Ausdruck hat einen Typ. Welchen Typ hat
dieser Ausdruck jetzt? Das könnt ihr noch nicht wissen,
aber vielleicht weiß es schon jemand,
kann mir das schon in den Kopf werfen hier.
Da wird jetzt irgendwas addiert. Ein Zeichen mit einer Zahl
. Was ist es dann? Das ist wieder ein Zeichen
oder ist es
eine Zahl
Intager. Okay, da sagt jemand, das ist Intager.
Also tatsächlich ist es hier 67 vom Typ Int.
Das ist wahrscheinlich auch ein bisschen überraschend.
Da gehen wir gleich noch ein bisschen drauf ein.
Ich werde das erläutern. Okay, also ganz wichtig ist
erst mal, jeder Ausdruck hat einen Typ in Java.
Das ist auch nicht in allen Programmiersprachen so,
aber in Java ist es so,
ich kann im Quelltext draufschauen und weil wir das können,
kann das ein Compiler erst recht.
Ein Compiler muss es wissen,
bei jedem Ausdruck,
welchen Typ
der Ausdruck hat
Okay, wir gehen jetzt nochmal so
ein bisschen durch die Begriffe durch, also ein Ausdruck.
Ja, eine Verarbeitungsvorschrift, habe ich schon gesagt.
Da werden Operanten mit Operatoren verknüpft. Häufig sind das arathmetische
oder logische Ausdrücke. Fünfmal x plus 3, arathmetischer Ausdruck,
wenn x eine Zahl darstellt. Was ganz wichtig ist,
wenn wir über Operatoren reden in solchen Ausdrücken,
dann muss man immer unterscheiden, den Operator und die Operation.
Ihr werdet auch gleich sehen, dass das ein ziemlich
wichtiger Unterschied ist
Dass Operator Zeichen, also hier so ein Plus,
minus ein Mal geteilt, das ist das Operator Zeichen,
das ist der Operator. Wir sprechen da auch kurz von
dem Operator. Die Operation, die damit verknüpft ist,
ist zum Beispiel bei dem Plus-Symbol hier wahrscheinlich die Addition.
Dummerweise ist das nicht ganz eindeutig. Welche Addition das ist,
weil es gibt verschiedene Additionen, die werden wir uns gleich ansehen.
Ja, also da kann man tatsächlich unterscheiden zwischen dem Zeichen,
der Operator und der Operation, die dann ausgeführt wird.
Okay, auch noch ein bisschen Grundlagen, Zeugs,
einfach so Begrifflichkeit, damit wir dann hinterher richtig einsteigen können,
das,
was Java uns da so anbietet
Es gibt Vereinbarungen über Operatoren. Also tatsächlich haben wir implizite Annahmen,
wie solche Ausdrücke ausgewertet werden. Meistens sind die ganz gut,
weil ihr hoffentlich eine relativ gesunde mathematische Grundbildung habt.
Das heißt, wenn ihr so einen mathematischen Ausdruck seht,
dann wisst ihr ungefähr, was da so rauskommt.
Das ist dummerweise in Programmiersprache nicht immer garantiert.
Programmiersprachen sind da einfach ein bisschen anders. Und
genau diese Unterschiede versuche ich jetzt hier sehr deutlich rauszuarbeiten.
Also es gibt so verschiedene Vereinbarungen über Operatoren,
die nennen wir hier Positionsstelligkeit, Präzedenz und Assoziationsreihenfolge.
Die gucken wir uns mal ganz kurz an
Ganz simpel, die Position, wo steht der Operator?
Steht der zwischen seinen beiden Operanten? Haben wir gerade gesehen,
iPlus 3, da steht der Plus-Operator zwischen seinen Operanten,
nennen wir Infix, ein Infix-Operator. Es gibt auch Präfix-Operatoren,
also zum Beispiel hier minus 2. Tatsächlich ist es so,
dass, wenn ich hier hinschreibe, eins,
dann ist das eine Eins,
ein Inliteral mit dem Wert Eins.
Und ich schreibe minus eins, dann ist das ein Operator,
der auf die Eins angewendet wird.
Das heißt, da steht wirklich eins und negiert um eins.
Ich kann nämlich auch hinschreiben, minus, leerzeichen,
minus eins.
Was kommt da raus
Minus minus eins ist, plus eins.
Ich weiß, ich langweile euch, ihr will.
Es ist halt einfache Mathematik. Aber das geht tatsächlich auch
. Das ist also tatsächlich ein Präfix-Operator. Das heißt,
der Operator steht vor seinem Operanten. Dann gibt es auch Postfix-Operatoren,
kennt ihr aus der Mathematik, so was,
drei Fakultät, da ist der Operator dann dahinter geschrieben.
Dann gibt es die Stelligkeit, einfach wie viele Operanten bekommt denn
der Operator, auf wie viele Operanten bezieht er sich?
Gibt es einstellig, haben wir gerade gesehen,
also so ein unnäherer Operator
Wie das Minuszeichen, was wir gerade gesehen haben,
oder eben halt auch in der Mathematik jedes Fakultätsymbol,
das wir in der Programmierung so erstmal nicht haben.
Zumindest in Java nicht. Zweistellige Operatoren, das ist so der Klassiker,
das ist für die Adition, die Multiplikation und so weiter.
Infix zweistellig. Es ist also zum Beispiel in Java hier
die Multiplikation. Und dreistellige Operatoren gibt es auch.
Ja, ist eher so ein bisschen außergewöhnlich.
Also zum Beispiel kann man das hier IF irgendwas,
denn irgendwas anderes, äls irgendwas Drittes,
das kann man auch als einen triadischen Operator auffassen,
dass da irgendwie zwei Dinge und so weiter.
Aber das ist eher, sagen wir, so ein bisschen fortgeschrittenes Zeug.
Es gibt aber auch einen dreistelligen Operator in Java,
der ist so am Rande wichtig.
Wer sich dafür interessiert, kann sich den mal angucken.
Nächster Punkt, Präzedenz von Operatoren.
Das ist wieder ziemlich wichtig und das ist so das,
was ihr auch kennt aus der Mathematik.
Also drei plus fünf mal sieben minus drei. Da würdet
ihr alle sagen, das ist vermutlich fünf mal sieben,
weil ihr zuerst die Punktrechnung durchführt.
Das ist 35 plus drei ist 38, minus 3 ist wieder 35.
Das ist was anderes, als wenn ich jetzt rechnen würde,
3 plus 5 ist acht und sieben
minus drei
ist vier
8 mal 4 sind 32. Das ist ein anderer Wert,
der da rauskommt. Klar, wenn ich also was anderes haben will,
als die Präzedenz Videooperatoren definiert sind, dann muss ich explizit klammern.
Das ist sowieso generell eine gute Idee,
explizit Klammern zu setzen, um wirklich das zu erreichen,
was man sich denkt als Programmierer.
Nicht irgendwie was hinzuschreiben und dann ist man überrascht,
was der Compiler daraus macht.
Solche Situationen werden wir heute noch sehen. Das heißt,
da gibt es Regeln für die Präzedenz. Das ist in jeder Programmiersprache,
ich will nicht sagen anders,
aber es ist eben halt für jede Programmiersprache ist es
speziell definiert,
wie die Präzedenzen aufgebaut sind
Der letzte Punkt ist die Assoziativität von Operatoren. Das heißt,
wenn es keine Präzedenzunterschiede gibt,
wie in diesem Fall hier, 5, minus 4,
minus 3, dann sind das ja zwei Operatoren.
So Praktionen, Minusoperator. Da gibt es keine Präzedenzregeln.
Da hat keiner irgendwie Vorrang und wird zuerst ausgewertet.
Da ist es wirklich eine Frage von, ja,
mache ich das jetzt von links oder von rechts?
Und das macht einen Unterschied. Also bei diesem Operator auf
jeden Fall. 5, minus 4 ist 1,
minus 3 ist minus 2. Wenn ich aber von rechts auswerte,
also zuerst 4, minus 3 rechne,
dann ist das irgendwie 1 und 5,
minus 1 ist
2 und minus 4 sind ziemlich verschieden. Das heißt also,
das ist in der Mathematik unserer Erwartung von links nach rechts,
gibt aber auch durchaus wieder Sprachen, wurde,
was dann auch von rechts nach links ausgewertet wird.
Vielleicht jetzt nicht gerade der Subtraktionsoperator, aber andere Operatoren.
Wenn von links nach rechts ausgewertet wird, sprechen wir von
Linksassoziativität unter der Operator, ist linksassoziativ und ansonsten rechtsassoziativ.
Das ist egal. Letzte Woche hatten wir hier diese Sache mit,
ist denn 3 plus 4 nicht das Gleiche wie 4 plus 3?
Ja, auf dieser Ebene jetzt ja. Letzte Woche haben
wir über Syntax gesprochen, da war das nicht egal.
Das sind verschiedene Symbi folgen. Und das hier,
da ist es tatsächlich so 3 plus 4 plus 5,
da ist es wirklich wurscht, wie ich das ausrechne,
aber das liegt eben an der Semantik der Operation, die dahinter steht.
Ganz zahlige Operationen ist halt kommunikativ, nee, assoziativ, assoziativ. So,
zentrale Operatoren habe ich jetzt hier schon so ein paar eingeführt,
also wir haben gesehen, die Multiplikation, die Division,
die Addition, die Subtraktion, dann gibt es diesen Modolo-Operator,
der ist ein bisschen speziell,
muss man sich dann auch in Ruhe mal angucken.
Dann gibt es hier so diese beiden etwas eigenartigen Operatoren
plus plus und minus
Also Erbstücke aus CC plus plus. Da will ich gleich
mal so ein kleines Beispiel zu zeigen.
Dann gibt es den einen entscheidenden Operator, die Zuweisung.
Ja, haben wir gesehen für die linke und rechte Seite.
Und dann gibt es hier noch für die Bulschen-Operatoren,
also für Bulsche-Operationen, die Operatoren.
Hier gibt es ein logisches Nicht-Ausrufungszeichen, wird als Präfix notiert in Java.
Und dann gibt es infix ein logisches und ein logisches Ose.
Das braucht man für bulsche Ausdrücke. Kommen wir noch drauf
. Und so Vergleiche von Zahlen und ähnliches.
Das ist so eine nette Übersicht hier. Ich mache mal
so einen kleinen kurzen Ausflug in die Frage,
wie das mit dem Plus Plus ist,
immer wieder gerne nachgefragt wird und auch immer wieder gerne falsch gemacht wird.
Ich empfehle ja immer, lass die Finger von diesen Dingern.
Also was man machen kann, ich habe in den Buchstaben Char gehabt.
Ich kann tatsächlich jetzt mit einem Char auch rechnen.
Ich kann jetzt sowas machen. Mal machen wir es mal so.
Plus plus Char, ja, dann kommt da B raus.
Ich kann tatsächlich irgendwie das Zeichen um eins erhöhen,
das ist das B. Kann es nochmal machen,
dann ist es das C. So, was ich jetzt aber zeigen will,
ist, ich habe eine Variable I,
habe ich die hier irgendwo 44.
So, jetzt kann ich schreiben, I plus plus.
Dann wird der Wert von I erhöht
Das ist richtig, diese Aussage. Was überraschend ist,
ist, dass der Ausdruck, so wie er da steht,
nicht 45 liefert, sondern was anderes.
Wenn ich das jetzt ausführe, kommt da 44 raus.
Aber I hat den Wert 45. Das heißt,
dieser beknackte Operator in der Postfix-Notation,
wie ich ihn gerade verwendet habe, also I plus plus,
bewirkt, dass I erhöht wird, nachdem der Ausdruck ausgewertet wurde.
Also erst mal innerhalb des Ausdrucks wird I einfach ausgelesen.
Und anschließend wird das erhöht. Das führt dazu,
dass ich, wenn ich sowas habe,
wie in J ist gleich I plus plus,
dann kriegt J den Wert 45, weil I hat,
dieses I Plus Plus hat als Ausdruck.
Der Wert des Ausdrucks ist tatsächlich 45. Das heißt, J ist dann 45,
aber I ist hinter den Kulissen erhöht worden, ist jetzt 46.
Völlig beknackt. Völlig unintuitiv. Da kann man sich so richtig schön
mit ins Knie schießen, wenn man irgendwie Ausdrücke macht,
wo man dann so einen Postfax drin hat.
Ich zeige es deswegen nur ganz kurz, weil immer so
viele Schlaumeier sagen, ach, das ist viel schöner.
Wenn ihr diesen Operator benutzt, dann bitte immer Präfix.
Wenn ihr nämlich jetzt schreibt, J ist gleich plus plus I,
wenn das unbedingt so wichtig ist,
dass das innerhalb einer Zeile passiert
Dann ist tatsächlich J, jetzt 46, nein,
J ist jetzt 47, weil das plus plus davor stand.
Also zuerst wird I erhöht. Und dann ist noch
das Ergebnis des Ausdrucks hier 47. Das heißt,
das Ergebnis des Ausdrucks und der Wert von I sind gleich.
Also hier jetzt J, 47 und I, auch 47.
Da seht ihr schon, diese Ausdrucksgeschichten sind so ein bisschen viel geliehen,
insbesondere bei so komischen Programmiersprachen, diese seltsamen Operatoren drin haben.
Die sollte ja am besten, lasst die Finger davon,
wenn ihr sie benutzen müsst, dann bitte immer Präfix,
auch in so Vorschleifen, die werden wir noch sehen.
Da schreiben wir eigentlich gerne immer beim Erhöhen dieses Schleifenzählers,
das als Präfix sind
Okay, hier nochmal die Übersicht. Das sind tatsächlich
alle Operatoren in Java. Ihr könnt die,
ihr könnt diese Menge der Operatoren nicht erweitern in Java.
Es gibt Programmiersprachen, da geht das. Ihr könnt auch nicht
die Semantik dieser Operationen irgendwie ändern. Also die Operationen,
die mit diesen Operatoren verknüpft sind, sind festgelegt in Java.
Einige der Operatoren haben mehrere Operationen drankleben. Das Plus zum Beispiel,
haben wir schon gesehen, String-Konkret der Nation und Itiger-Addition.
Da ist eine Frage
Wenn man jetzt zwei verschiedene, auf den gleichen Ausdruck bringt,
aber es da verschließt nicht mal so eins als Streaming und eins zu eins in beispielsweise.
Ich dachte, da ist es zurück. Okay,
er stellt die Frage, wie ist das denn bei so einer Zuweisung,
wenn tatsächlich die Typen nicht zueinander passen,
also wenn da jetzt irgendwie steht, String ist gleich
int oder int ist gleich string, sowas, ja.
Können wir uns einfach mal angucken. Ich kann ja hier
zum Beispiel, habe ich jetzt eine Variable I,
da kann ich ja schreiben, ist gleich hallo.
I sei gleich hallo, I ist vom Typ int,
hallo ist eine Zeichenkette
Das sollte jetzt in die Hose gehen und zum Glück sagt der Compiler auch,
hey, was willst du denn da tun?
Du willst etwas machen, was nicht gehen kann.
Du kannst nicht in einer Intvariablen eine Zeichenkette speichern. Das heißt,
in Java wird tatsächlich der Compiler das überprüfen und wird euch auch auf die Finger klopfen.
Einer der Vorteile, dass man explizit Typen deklarieren muss.
Frage beantwortet? Ja. Okay, gut. Hier nur diese Übersicht,
das ist eine sehr kompakte Darstellung,
die ist aber extrem nützlich, weil hier praktisch alles drinsteht,
was hier über Operatoren in Java wissen müsst.
Erstmal seht ihr hier die blaue Gefärbten,
die so ein bisschen fett hervorgehoben sind, das sind die,
die wirklich auf Level 1 jetzt für uns auch video sind
In Form werden wir die See. Wir haben jetzt hier gesehen,
schon den Prozeduraufruf, also den Methodenaufruf, die Punktnotation,
die Negation, die das unnähere Minus.
New habt ihr schon gesehen, das werden wir uns gleich angucken mit diesen Klammern hier.
Das nennen wir dann eine Typumwandlung, die man dann machen kann.
Und dann gibt es hier so die üblichen Operatoren, binäre Operatoren.
Das sind fast alles binäre. Hier steht so ein kleiner
Stern dran. Das ist nämlich der einzige teernähere Operator.
Das ist so ein komisches If, das man irgendwie anders hinschreiben kann.
Nicht wichtig für Spezialisten, wer sich das angucken will,
gerne. Aber wichtig sind hier die Blaugefährten. Okay,
wir haben jetzt schon jetzt gesehen Zuweisungen,
spielt eine wichtige Rolle in der imperativen Programmierung.
Das ist eine Form von Anweisung. Also Anweisungen sind generell
die Dinge, die irgendwas tun in einem Imperativ oder objektnotierten
Programm und eine Art von Anweisung ist die Zuweisung.
Anweisungen werden textuell da ausgeführt und verändern eben halt auch die Belegungen von Variablen.
Das müssen sie nicht machen, aber das machen sie häufig. Variablen,
da kennen wir Exemplarwarium, formale paramete lokale Variablen,
linke Seite, rechte Seite, links immer ein Ziel,
irgendein Behälter, muss eine Variable sein, rechts ein Ausdruck.
Und dann haben wir halt gesehen,
es atmetische und Bullshow-Ausdrücke sich aus Operanten und Operatoren zusammensetzen
Okay, soweit so gut. Wir wollen uns das
ja gleich alles mal ein bisschen konkreter ansehen in Java.
Vorher will ich nochmal so ein paar Dinge sagen zu den Dingern, die da jetzt mit reinspielen.
Wir haben jetzt hier schon gesehen in diesen ganzen Beispielen,
hier zum Beispiel steht eine 47,
ich habe irgendwo auch hier so ein Zeichenketten,
ein Zeichen literal angeben, ich habe eine Zeichenkette angegeben,
das sind alles so Dinge von,
das sind so Zeichenfolgen im Programmtext,
die ein Compiler erkennt und die auch in Java eine sehr spezielle Bedeutung haben.
Letztendlich sind das nämlich
alles Dinge von den elementaren Typen
Und diese elementaren Typen solltet ihr auch kennen. Es gibt
eben halt einen bestimmten Satz von elementaren Typen in Java.
Mit denen sollte man ein bisschen umgehen können. Und weil dann
alles andere darauf aufbaut. Es ist tatsächlich auch so,
dass wir bisher mit euch, wenn ihr selber Klassen geschrieben habt,
dann hattet ihr als Exemplarvariablen für die Typen,
der Exemplar war, immer nur so primitive Typen.
Wir haben immer gesagt, mach dann in oder mach dann einen Bulien oder ähnliches.
Diese Woche in den Übungen wird das weitergehen.
Ihr werdet also Klassen schreiben, die sehr einfach sind.
In dem Sinne, dass dann diese Belegung dieser Felder
völlig unabhängig sind von anderen Objekten
Ab der nächsten Woche wird das sich fundamental ändern.
Dann geht es plötzlich um Referenzen, da können Objekte miteinander verbunden sein.
Das gucken wir uns erstmal noch nicht an.
Wir haben noch eine relativ einfache Welt.
Das heißt also bei uns, die Felder nur elementare Typen.
Wir haben also relativ einfache Objekte, wo wir sagen können,
der Zustand des Objektes hängt lediglich davon ab,
wie die einzelnen Felder belegt sind.
Okay, aber die müssen wir uns jetzt mal ein bisschen
genauer angucken. Und jetzt haben wir schon relativ viel,
habe ich jetzt so implizit gesprochen über Typen.
Gerade diese Frage ging auch in die Richtung.
Wie ist das denn, wenn die Typen nicht zueinander passen?
Aber was ist überhaupt ein Typ? Auch die Frage
werden wir uns nächste Woche ziemlich ausführlich angucken
Den Typbegriff mal näher zu beleuchten. Hier erstmal nur für
uns richtig relevant und wichtig. Was macht ein Typ?
Er legt eine Wertemenge fest und die zulässigen Operationen. Das heißt,
sowas wie Int, als Beispiel jetzt in Java,
das ist ein Typ, besteht aus zwei Bestandteilen.
Eine Wertemenge, also tatsächlich in Java oder in irgendeiner Sprache
von minus zwei hoch 31 bis zwei hoch 31 minus eins.
Das ist einfach die Menge aller möglichen Int-Zahlen.
Und dann gibt es noch zulässige Operationen, also das,
was man mit denen machen kann.
Zum Beispiel über die Infix-Operatoren. Plus minus Mal und so weiter.
Und da muss man sich ganz deutlich vor Augen führen,
dass eben halt bei dem Typ Int man nur ganz zahlige Additionen machen kann.
Und auch nur ganz zahlig subtrahieren kann, auch nur ganz zahlig multiplizieren kann.
Das ist etwas, was vielen Leuten Probleme macht.
Da gehen wir heute ein bisschen genauer darauf ein,
den Unterschied zwischen Int und Float beziehungsweise Double, also diese Gleitkommazahlen.
Aber erstmal für euch wichtig, für jeden Typ gilt,
es gibt eine Wertemenge und es gibt Operationen auf diesen Werten,
wo man dann irgendwie mit diesen,
wo man Werte verknüpfen kann,
miteinander eine Beziehung setzen kann
Okay, und praktisch jede Programmiersprache hat irgendeinen elementaren Typ.
Also irgendwas wird da immer angeboten. Für ganze Zahlen,
irgendwie sowas wie Integer, für reelle Zahlen, also Gleitkammer-Zahlen,
sowas wie Float oder Reel, je nach Programmiersprache.
Das ist jetzt Programmiersprachen unabhängig. Zeichen, sowas wie Cha,
also dass man einzelne Zeichen haben kann und wahrheitswerte Typ Bulien.
Das ist so der Minimalsatz, den man eigentlich in fast jeder Sprache hat.
Also ganze Zahlen gibt es eigentlich in jeder Sprache. Und Butsche-Werte auch,
relle Zahlen muss es nicht in jeder Sprache geben,
das mit dem Zeichen ist auch so in den meisten
pragmatischen Sprachen
dann schon
Was ganz wichtig ist, ist, für diese elementaren Typen
gibt es immer etwas, was man direkt hinschreiben kann.
Ich kann die Werte direkt notieren. Also wenn ich jetzt hier tatsächlich in dieser Direkteingabe sage,
5, dann ist das der Wert 5,
also 5 ist ein Literal oder 42, ist eine Zeichenfolge,
4 und 2, wird aber interpretiert als eine Zahl vom Typ in.
Und der Typ wird auch tatsächlich gleich bestimmt hier,
also weil da ist die Direkteingabe in Blue Jay ganz hübsch,
die sagt gleich, aha, das ist übrigens diese Zeichenfolge,
interpretiere ich als von dem und dem Typ.
Also wenn ich jetzt hierhin schreibe,
irgendwie großes A, in einfachen Anführungsstrichen,
dann ist es halt
ein Char
Und wenn ich jetzt hier hinschreibe, 2.5,
dann ist das ein Double, weil da ein Punkt drin steckt.
Aber ganz wichtig ist, diese Zeichenfolgen, wo man den
Wert direkt ablesen kann, die Dinger nennen wir Literale.
Während wenn ich sowas habe, wie ich,
dann kann ich jetzt 47 sein und wenn ich jetzt irgendwie sage,
iPlus Plus, dann ist i immer noch 47,
aber wenn ich es dann mir angucke, ist es 48,
ich habe es wieder Postfix verwendet.
So, das kann sich also ändern, während die 42
ist immer die 42, wird sich auch nie ändern in Java.
Das ist also eine Zeichenfolge im Quelltext die wirklich einem konkreten Wert zugeordnet ist.
Auch so Zeichenketten sind Literale. Alu, was immer das heißen mag.
Ihr seht hier, Blue Jay zeigt sofort, das ist ein String.
Da weiß man an diesen doppelten Anführungsstrichen. Okay. So,
jetzt gibt's, ich habe es schon angedeutet,
Zahlen in Programmiersprachen schwierig, insbesondere in Java, ein bisschen hakelig.
Das liegt wieder daran, dass diese Programmiersprache endlich nur
eine Abstraktion ist über der von Neumann-Maschine.
Ich habe letzte Woche erzählt, von Neumann-Maschine, Speicher,
Zellen, in denen irgendwelche Werte abgelegt sind.
Da ist es einfach so, in dem Hauptsprecher haben diese
einzelnen Zellen eine bestimmte Breite. Also heutzutage vielleicht 64-Bit,
früher 32, früher 8. Also irgendwo, wie viele Bits hat ein Wort?
So, und wenn man diese Wortlänge einfach hat,
dann ist es eine ganz klare Begrenzung.
Und pragmatisch ist es so, dass die meisten Programmiersprachen sagen,
wir legen einen Wert eines Typs immer in einem solchen Wort ab,
also in und die werden üblicherweise tatsächlich in einem Wort abgelegt.
Das ist in unterschiedlichen Programmiersprachen durchaus unterschiedlich geregelt.
Da ist nicht festgelegt, wie breit ein bestimmter Typ ist.
In Java ist das genau festgelegt, das nehmen wir uns
auch noch genauer an. Aber das führt dazu,
dass wenn ich so in so einem Wort eine begrenzte Anzahl von Bizza habe,
kann ich auch nur begrenzt viele Werte darstellen.
Das heißt, ich kann nicht so wirklich alles machen,
was ich mir so vorstelle. Also zum Beispiel in Java,
mir mal diese Zahl 9, 8, 7,
6, 5, 4,
3,
2,
Das ist eine ziemlich große Zahl. Das sind irgendwie 987 Millionen.
So. Ist vom Typ Int. Jetzt kann ich das addieren mit 9,
8, 7, 6, 5, 4,
3, 2, 1. Und dann kommt irgendwas raus.
Das sind jetzt so fast zwei Milliarden. So,
wenn man sich ein bisschen auskennt mit Java, weiß man Int,
da ist die obere Grenze irgendwo bei zwei Milliarden.
Also wenn ich jetzt also das hier nochmal addiere mit,
sagen wir, 9, 8, 7, 6,
5, 4, 3, 2,
1, dann kommt da was raus,
was oberhalb von zwei Milliarden ist.
Das kann dann in dem einen Wort in diesen 32 Bit
nicht mehr dargestellt werden.
Also kommt da irgendwas anderes raus.
Was kommt da raus
Was passiert jetzt hier? Was passiert, wenn ich das
jetzt mache? Also die Zahl ist nicht mehr darstellbar.
Gibt es eine Fehlermeldung? Was sind so der Einschätzung, ja?
Ich meine, der Effekt von mir hat es erzählt.
Er sagt, er fängt bei null wieder an zu zählen,
da sagt, da kommt eine Negativzahl raus,
sagt er, sonst noch Meinungen dazu, ja?
Ja, dementsprechend. Okay, es gibt einen Überlauf,
sagt er und entsprechend kommt da irgendwas raus und negative Zahl.
Ist so ein Überlauf, hört sich das,
hört sich fies an, ist schmerzhaft oder?
Also tut das weh, so ein Überlauf?
Also was passiert, gibt es eine Fehlermeldung oder ist
ein Überlauf was ganz Normales
Ja. Meistens ist das ja auch so,
bei 10 gab es sowas wie Rap-A-Round,
das ist halt die ganze Zeit da vorne.
Ja. Tatsächlich ist es ja so, dass da jetzt
irgendeine negative Zahl rauskommt. Man kann sich das so vorstellen,
dass quasi das Modulo ist. Das heißt also,
es wird wieder im Zahlenbereich von 0 bis 2 Milliarden und
dann geht es hinten bei 2 Milliarden wieder weiter und dann wird sozusagen das so einmal so,
das liegt daran, wie diese ganzen Zahlen abgelegt sind.
Das ist in Java sehr klar definiert, nämlich im Zweierkompliment.
Das Zweierkompliment ist eben letztendlich so ein Modulo-Zahlendarstellung.
Das ist ein Rechnerdetail. Aber damit müssen wir umgehen,
dass das so ist. Es gibt also immer irgendwie
eine kleinste und eine größte
ganze Zahl
Einem Wort. Es gibt Programmiersprachen, da ist das nicht so.
Es gibt Programmiersprachen, da kann ich beliebig große Zahlen formulieren.
In Java ist es so, dass es eben halt eingeschränkt ist.
Das ist soweit noch schön bei ganzen Zahlen.
Bei Gleitkommazahlen wird es noch ein bisschen haariger.
Wir haben bei ganzen Zahlen einen begrenzten Zahlenbereich,
minus zwei Milliarden bis plus 20 Milliarden bei Int.
Aber wenn ich da drin bleibe mit meinen Rechnungen,
da kann ich ja ein bisschen darauf achten, dann ist alles prima.
Dann habe ich keine Genauigkeitsverluste. Bei den Gleitkammazahlen ist das ein bisschen fieser.
Die haben erstens, die haben zwar weit viel größeren Wertebereich,
aber dummerweise sind zwischen den Werten Lücken,
da können dann bestimmte Zahlen gar nicht dargestellt werden.
Und das kann ziemlich übel sein,
und das ist insbesondere bei den Gleitkammerzahlen so, alles,
was weit weg ist von der Null,
da werden die Lücken immer größer.
Und dann kann man sowas wie hier zum Beispiel X plus,
Y, minus Y, würde man normalerweise mathematisch annehmen,
ist X. Ist aber nicht immer so.
Bei Gleitkammerzahlen. Ziemlich fies. Das werden wir auch
diese Woche in den Übungen so ein bisschen thematisieren.
Das ist ziemlich fundamental ein Problem der Darstellung von Zahlen,
der Arrithmetik aufrechnen. Da muss man sich mit auskennen.
Da werdet ihr mehr drüber hören in Rechnerstrukturen.
Das ist eine Parallelveranstaltung für die meisten von euch.
Wer die Veranstaltung nicht hört, da kann man sich ein bisschen schlau machen.
Also Zweier, Kompliment und auch Gleitkommazahlen-Darstellung.
In Java ist das Eye Travel E 754,
sage ich gleich noch ein bisschen mehr dazu nach der Pause.
Aber hier gilt erst mal, was wir versuchen,
jetzt euch zu sagen hier ist.
Wir wollen nämlich nicht in diese Gleitkommazahlen-Darstellung intensiv einsteigen.
Das ist ein Thema für eine andere Veranstaltung.
Aber ihr habt natürlich diese Dinger in Java. Und was
wir euch sagen, ist, lasst die Finger davon.
Tut uns den Gefallen, wenn ihr nicht genau wisst,
was ihr tut, dann lasst die Finger davon.
Ich habe früher immer gerne gesagt,
hier gibt es einen Artikel von David Goldberg,
whatevery computer scientist, should know about floating point areasmatic.
Das Ding hat Schlappe 40 Seiten, 42 Seiten,
die sind richtig lustig zu lesen.
Richtig schön. Also wer mir den Artikel,
wer den durchliest und mir erklären kann,
der kriegt einen Snickers von mir.
Da bin ich echt großzügig. Das ist nämlich eine ganz
schön dicke Nummer. Also Gleitkomma-Arathmetik ist wirklich richtig anspruchsvoll.
Und wir sagen nicht, dass man Gleitkommazahlen nicht verwenden sollte.
Wenn man weiß, was man tut, gerne.
Aber wenn man nicht weiß, was da passiert,
dann lasst die Finger davon.
Mit ganzen Zahlen rechnen kann man fast alles hinkriegen,
was man
so rechnen muss
Man kommt ziemlich weit mit ganz zahliger Arrithmetik. Bei den Problemen,
die man üblicherweise zu bearbeiten hat. Also hier Donald Knus,
einer der großen der Informatik, hat zum Beispiel Tech.
Vielleicht kennen einige von euch Latech, das ist darauf aufgesetzt.
Komplett mit Festkammerzahlen gemacht. Hier nochmal angedeutet,
dieser Wertebereich hier von den Gleitkammerzahlen, um die Null rum
liegen die sehr dicht, die darstellbaren Zahlen von den Gleitkammerzahlen.
Je weiter von der Null weg, desto größer werden die Lücken.
Das geht sogar so weit, dass da die Lücken über ganze Zahlen hinausgehen.
Dass wenn wir uns nach der Pause etwas intensiver angucken,
wenn jetzt nicht noch Fragen sind, zu dem,
was ich bis jetzt erzählt habe,
dann können wir jetzt 5 Minuten Pause machen.
So, es geht weiter. 5 Minuten sind rum.
Bitte langsam wieder zu den Plätzen zurückkehren.
Jetzt gibt es Butter bei die Fische. Das heißt,
jetzt gucken wir uns ganz konkret an,
wie ist es denn in Java gebaut.
Also bisher habe ich so ein bisschen was Allgemeines gesagt zu Zahlendarstellungen.
Aber jetzt gucken wir es uns einfach mal wirklich an,
wie es in Java ist.
Elementare Datentypen in Java
gibt es genau
Acht Stück. Es gibt vier verschiedene ganz zahlige Typen,
nämlich White Short, Int und Long. Int habt ihr
schon kennengelernt und Int definiert Java tatsächlich 32 Bit zahlen.
32 Bit Zweier Kompliment. Zweier Kompliment ist, wie gesagt,
eine Art der Zahlendarstellung. Es gibt auch Short, 16 Bit,
es gibt auch beide acht Bit und es gibt Long 64 Bit.
Hier sind die Wertebereiche mal so ein bisschen aufgeführt.
Man sieht also Byte als die kürzeste Darstellung,
da geht es eben halt von minus 128 bis plus
Short im entsprechenden minus 32.000 bis plus 32.000,
in minus zwei Milliarden bis plus zwei Milliarden und Long ist ziemlich groß.
Das ist ziemlich groß. Da kann man schon
eine Menge Zahlen unterbringen. Das sind die ganzen Zahlen.
Dann gibt es zwei Typen für Gleitkammer-Zahlen, Float on Double,
Float definiert mit 32 Bit, Double mit 64 Bit.
Auch da werde ich gleich noch ein paar Morgen mehr Worte zu sagen.
Dann gibt es einen Bullshit-Datentyp, der heißt Bulien.
Und dann gibt es einen Typ für Zeichen,
nämlich Cha
Schaas definiert das ja tatsächlich 16-Bit einnimmt.
Also tatsächlich die Charles können 65.000 verschiedene sein, ungefähr.
Was ganz lustig ist, ich habe vorhin schon gezeigt hier,
könnt ihr bei dir die Tür zumachen, bitte?
Oder reinkommen oder rauskommen? Danke. Wenn ich jetzt hier
zum Beispiel die Null eingebe, dann ist das Int.
Ich kann aber auch schreiben, null.null.
Dann ist es
ein Double
Und ich kann auch schreiben, minus 0.0, dann ist es
auch ein Double, aber das ist die minus null.
Es gibt also verschiedene Nullen in diesen verschiedenen Typen.
Das heißt, die null ist ein Literal,
das hier bei den ganzen Zahlen beheimatet ist,
die 0.0 ist ein Literal, das hier für die Gleitkammerzahlen gedacht ist.
Tatsächlich gibt es in diesem Zahlensystem bei den Gleitkammerzahlen eine negative Null und eine positive Null.
Ziemlich sinnlos, aber es ist halt so. Was auch wichtig ist,
dass alle Typen so einen Standardwert haben, der ist wichtig,
haben wir ja gesehen für die Zustandsfelder,
also für die Zustandsvariablen,
für die Exemplarvariablen
Dass ich, wenn ich eine Variable da deklariere,
dass dann auch klar ist, wie sie belegt ist.
Bei den ganzen ganz zahligen Typen ist das null,
beziehungsweise 0L. 0L ist die Schreibweise für, oh,
das kann ich auch nochmal schreiben,
0L. Ist ein Long, ist ein Long null.
64 Bit null, das andere ist die 32 Bit null.
Also da sieht man schon, das ist nicht so ganz ohne.
Auch hier nochmal null mit einem großen L, auch ein Long.
Der Default-Wert, der Standardwert für Bulien ist Falls.
Also wenn ich eine Bullshit-Variable deklariere,
also hier Bulien
Ja, dann ist B. Falls. Kommen wir gleich noch
ein bisschen genauer drauf. Double, wie gesagt,
0.0 und 0.0F. Auch da nochmal diese Unterscheidung,
0.0 ist ein Double, haben wir eben gesehen.
Wenn ich ein F dahinter schreibe, ist es ein Float.
Ein Float 32-Bit, 0.0, 64-Bit.
Und beim Char ist es tatsächlich das Zeichen mit der Originalzahl 0.
Also hier irgendwie, wir können mal gucken,
was das ist, das kann man leider nicht darstellen.
Also wenn ich sage Char, XY,
deklariere und jetzt mal mir angucke, was ist denn XY,
dann ist das irgendwas, was nicht darstellbar ist.
Weil das Zeichen mit, im Zeichensatz, das allererste Zeichen
mit dem nullten Index in dem Zeichensatz ist nichts Darstellbares.
Gucken wir uns gleich genauer an. So,
das erstmal jetzt, dass es diese Datentypen gibt.
Alles, was ich jetzt erzähle, ist in Übersicht.
Man kann sich da beliebig intensiv mit beschäftigen,
insbesondere mit den Problemen, die sich zwischen diesem Typen ergeben.
Ich gehe da heute drauf ein, auf die Grundideen,
auf die Grundkonzepte, aber ihr müsst euch die Sprachregeln dann
vielleicht nochmal einfach vertieft ansehen.
Das erste ist, was wir jetzt schon gesehen haben,
Zeichen. Zeichen werden im Rechner eben halt durch Werte
eines Zeichensatzes repräsentiert
Wir haben das in Java schon gesehen. Einfache Anführungsstriche,
einzelnes Zeichen, das ist dann ein Literal für ein Zeichen.
Und das ist natürlich dann auch immer wieder wichtig zu sagen.
Also wenn ich hier hinschreibe, vier, dann ist das was anderes als die vier.
Das eine ist ein Int, das andere ist ein Char.
Wird nicht verschiedene Dinge. Ich kann mit diesen Chars auch rechnen. Ich kann zum Beispiel sagen,
ich habe hier meinen Char-CH, der ist momentan,
hätte das große C. Ich kann jetzt schreiben, Iii,
meine Variable Ii, meinem Kunstgucken, er hat 48,
sage ich jetzt mal, Ii ist gleich CH.
Ich kann also tatsächlich dieses Zeichen zuweisen einer Int-Variable.
Und dann ist es eben halt 67. Also anscheinend hat es
C im Zeichensatz, das 67. Zeichen.
Von dem Zeichensatz, der hier verwendet wird in Java.
Tatsächlich ist es so, dass Java den Unicode verwendet und
der Unicode basiert auf dem Asky-Code.
Der Asky-Zeichensatz ist sozusagen der Vorgänger von Unicode.
Das sind beides Zeichensätze. Hier ist der Asky-Zeichensatz
Der ist schon ziemlich alt und auf vielen Heimcomputern
üblich gewesen und sehr verbreitet und steckt, wie gesagt,
auch heute noch in dem Unicode, ganz unten im Zeichensatz mit drin.
Das heißt, diese Belegung, die ihr hier seht,
in dieser wunderbaren Tabelle, da ist gelb hervorgehoben,
da sind die druckbaren Aski-Zeichen, man sieht also hier,
das Zeichen Null ist nicht druckbar, das ist irgendetwas komisches.
Und hier sieht man jetzt verschiedene Symbole, dann sind ja
die Großbuchstaben, die gehen also hier bei 65 los.
Also tatsächlich, wenn ich jetzt hier sage,
Chasa sei jetzt ein großes A, dann ist I gleich.
Char liefert mir tatsächlich dann den Zahlwert, also den Originalwert des Zeichens im Zeichensatz.
Also 65. Und tatsächlich ist das 65. Zeichen im Zeichensatz,
ist das große A. Und jetzt kann man tatsächlich mit Charles auch rechnen.
Ich kann also jetzt tatsächlich sagen, Char,
machen wir lieber wieder plus plus Char,
dann ist es das B. Das heißt,
ich habe einfach gesagt,
nimm das nächste Zeichen aus dem Zeichensatz an der Indexposition
65. Okay
Java verwendet den Unicode, und zwar den Unicode UTF 16.
Es gibt UTF 8, es gibt UTF 16,
und es gibt auch UTF 32. Java basiert auf UTF 16.
Das heißt, ein Char in Java ist 16-Bit breit.
Das ist einfach so. Das heißt, theoretisch könnt ihr
mit 65.000 verschiedene Zeichen dargestellt werden. Es ist aber so,
dass da bestimmte Teile von reserviert sind für eine erweiterte Zeichenkodierung.
Das heißt, man kann da mehr als 65.000 Zeichen mit
dem Unicode kodieren. Da haben die so ein bisschen getrickst.
Das gucken wir uns im Detail nicht an.
Das müsst ihr auch nicht verstehen, was wichtig ist
für euch ist
Ein Zeichen in Java wird in 16 Bit codiert.
Und ihr wisst, dass wir im Deutschen schon so komische Zeichen haben,
wie eine Umlaute. Die müssen ja auch irgendwie dargestellt werden.
Und das geht eben halt mit UTF 16 ganz gut.
Mit UTF 8 ist das auch teilweise möglich.
Das ist der 8-Bit-Zeichensatz. Das sind dann 256 Zeichen.
Aski hatte ja nur, wenn man das hier genau geguckt,
so 128 Werte. Und das gibt so verschiedene Möglichkeiten,
die Bereiche so zwischen 128 und 226 mit verschiedenen Werten zu belegen.
Das kommt dann, da kommen diese Effekte,
dass wir ja auf dem einen Rechner der Datei öffnen,
dass es dann völlig kaputt aussieht auf einem anderen Rechner
Weil die verschiedenen Zeichenkodierungen haben. Mehr über Unicode könnt ihr natürlich
auch im Internet finden. Was noch ganz interessant ist,
ist, dass ich ein Zeichen auch anders notieren kann.
Das ist etwas, was wir sowieso uns gleich noch genauer angucken.
Da ist eine Frage. Oh, gute Frage.
UTF ist die Abkürzung für, ich weiß es nicht.
Lässt sich aber nachgucken, glaube ich. Ich würde mal sagen,
Unico Textformating, keine Ahnung, ich rate, ich rate.
Tatsächlich kalt erwischt, habe ich,
weiß ich jetzt nicht
Hier ist die Webseite, wir können ja mal eben nachgucken.
Nee, machen wir jetzt nicht. Was auf jeden Fall
wichtig ist, ich kann einzelne Zeichen auch anders notieren.
Also ich kann es so machen, wie ich es hier
gemacht habe, einfaches Hochzeichen und ein großes A hinschreiben.
Ich kann aber auch alternativ die Originalzahl angeben.
Also zum Beispiel beim A ist es ja die 65,
ich kann auch schreiben und jetzt schreibe ich hier ein Backslash-U
und dann nehme ich hier 00 und jetzt muss ich überlegen,
die 65 in Hexa dezimal, Hexa dezimalzahlen,
die sind hier,
Moment,
die sind hier
Ein Zahlensystem auf der Basis 16. Wir kennen das Zahlensystem auf der Basis 10,
üblicherweise bei allem, was wir so an Zahlen im Alltagsgebrauch haben.
Hexziffern sind ein bisschen anders. Da sind die, das ist einfach auf der Basis 16.
Das heißt, wir brauchen Ziffern für die Zahlen 10,
11, 12, 13, 14, 15.
Und das ist eben halt A bis F. So,
das heißt, wenn ich jetzt so eine Zahl habe,
wie ihr hier 00 und jetzt will ich die 65 darstellen,
das ist 65 Dezimal,
ist 4 mal 16 plus 1. 4 mal 16 bis 64 plus 1 ist 65.
Also müsste das 4, 1 sein.
Das ist die Hexadezimalkodierung für das große
Sollte also auch ein A sein. Ja, ist auch
ein A. Da sehen wir jetzt schon den Effekt.
Ich kann denselben Wert mit unterschiedlichen Literalen repräsentieren. Das ist hier
deutlich und wir werden das gleich noch deutlicher sehen bei den Zahlen.
Das ist, wie gesagt, relativ häufig so,
dass man diese Hexe von für solche speichernahen Darstellungen benutzt.
Und Zeichen sind da eben halt keine Ausnahme. So,
Literale für Zahlen, jetzt haben wir so ein weiteres Beispiel dafür,
dass man tatsächlich dasselbe unterschiedlich formulieren kann
Also zum Beispiel, wenn ich hier hinschreibe,
minus eins, dann habe ich eben schon gesagt,
das ist eigentlich nicht die minus eins,
sondern das ist eigentlich eine Eins, die negiert wird.
Weil dieses minus eins ist ein Operator. Ich kann ganze Zahlen,
auch, das ist hier da als Beispiel,
sehr schön zu sehen, kann ich ja direkt hier zeigen,
die 29 zum Beispiel, kann ich Dezimal hinschreiben,
so wie wir es alle kennen. Ich kann aber auch,
sie oktal hinscheiden, ein weiteres Zahlenformat,
das die Informatiker mögen, 0-3, 5,
wenn ich ein ganz zahliges Literal mit einer Null einleite,
dann heißt das so viel wie, Compiler.
Alles, was jetzt kommt, interpretiere bitte als eine Oktalzahl.
Also 035. Ich dürfte jetzt an dieser Stelle nicht schreiben,
0333 09, weil 9 ist natürlich keine gültige Ziffer im Oktalsystem.
Integer number to large 039. Aber ich kann null 35 machen.
Das ist nämlich 3 mal 8 plus 5. 24 plus 5 ist
29. Also ist es auch die 29. Eine andere Darstellung für
dasselbe. Oder ich kann es auch hexadezimal darstellen,
haben wir gerade kennengelernt, diese Hexadezimaldarstellung.
Das ist 16 plus 13. 16 ist 1 und dann
13 ist
Also, 0X, damit leite ich sozusagen als Prefix ein.
Jetzt kommt eine Hexer-DC-Mahlzahl und dann irgendwie, was habe ich gesagt, 1D.
Und es ist die 29. Es ist für bestimmte rechnernahe Aktivitäten
praktisch, wenn man das so hinschreiben kann.
Im Allgemeinen braucht ihr das nicht. Also,
ihr könnt mit den Dezimals Hand durchaus umgehen.
Das ist schon in Ordnung. Dann haben wir hier Gleitkammerzahlen.
Da habe ich auch noch mal so ein paar Alternativen.
Ich kann schreiben, minus 0.5, das ist ein Double.
Ich kann die gleiche Zahl aber auch schreiben als minus
Mal 10,
hoch minus 1. 10 noch minus 1 ist 0,5, nee,
10 hoch minus 1, ein Zehntel, ein Zehntel,
10 noch minus 1 ist ein Zehntel und ein Zehntel von 5 ist 0,5.
Also ist das auch minus 0,5. Das ist also die Möglichkeit,
ich kann aber auch schreiben, fünf im Moment,
minus 50 mal 10 hoch minus, stopp, E10 hoch minus 2.
Da habe ich mich vertippt.
So, 50 EU minus 2 ist auch minus
Also es ist 50 mal 10 hoch minus 2, also ein Hundertstel,
50 mal ein Hundertstel oder 5 mal ein Zehntel oder das
sind alles die gleichen Darstellungen, verschiedene Darsteller für die gleiche Zahl.
Ziemlich bescheuert, kann man sagen. Aber sollte man
mal gesehen haben und verstanden haben. Ganz wichtig ist,
dass ihr immer wisst,
dass wenn ihr so ein Literal als Gleitkammer literal hinschreiben wollt,
immer so einen Punkt da reinsetzt, ihr könnt auch schreiben,
null Punkt, dann ist es automatisch schon als Gleitkammerzahl erkannt.
Und immer, wenn ihr nichts dazu schreibt, ist es
halt ein Double. Dann nimmt der Compiler automatisch an,
ihr wollt da die doppelte Genauigkeit haben,
64 Bit
Okay, dann haben wir relativ viele binäre Operatoren.
Haben wir schon gesehen. Und jetzt ist wieder ganz wichtig,
dass die binären Operatoren für ganze Zahlen,
und die gucken wir uns jetzt als erste an,
alles ganz zartig machen.
Das ist keine Überraschung bei 3 mal 5. 3 mal 5
ist 15. Aber wenn ich schreibe 20 durch 6,
dann sind die meisten Studierenden überrascht, dass da 3 rauskommt.
Also ich schreibe hier hin, 20 durch 6.
Und es kommt 3 raus. Weil das die ganz zahlige
Division ist. Wenn ich jetzt schreiben würde,
20.0 durch 6.0, dann dividiere ich, Gleitkommer zahlen.
Und dann kommt auch was anderes aus. Dann kommt da
irgendwie 3,3333 und am Ende eine kleine 5,
rund um 5 hier so am Ende.
Sehr schön. Da sieht man schon wieder, wie nett diese Gleitkammerzahlen sind.
Dasselbe Symbol, derselbe Operator, aber eine andere Operation.
Es werden Gleitkommerzahlen dividiert. Und dann kommen tatsächlich gebrochene Zahlen raus.
Hier gibt es dann in Jabba noch diesen Modulo-Operator, also 20,
Modulo 6 ist 2. Also 20 geteilt durch 6 ist 3.
Also der Rest des, wenn man 20 durch 6 teilt
Das ist dieser Modulo-Operator. Und Präzedenz,
wie erwartet also hier zweimal zwei, hat eine höhere Präzedenz.
Diese Präzedenztabelle habe ich ja vorhin schon gezeigt. Wenn ihr
die Tabelle rausnehmt, könnt ihr eigentlich alle Fragen beantworten,
die irgendwie noch kommen könnten zu solchen Ausdrücken.
Dann gibt es Vergleichsoperatoren. Da kann ich zum Beispiel
Zahlen vergleichen miteinander und es kommt immer ein Wahrheitswert raus.
Also irgendwie ist zwei größer als eins, natürlich ist True.
Das geht wunderbar. Größer gleich, kleiner und
so weiter. Kann man alles miteinander vergleichen
Da gibt es zwei weitere Infix-Operatoren für Gleichheit und Ungleichheit.
Also ist drei ungleich zwei. Ja, natürlich.
Ziemlich offensichtlich. Und da ist es tatsächlich so,
diese Vergleichsoperatoren haben gegenüber den Arithmittischen Operatoren eine niedrigere Präzedenz.
Das heißt, wenn ich sowas habe,
hier drei gleich gleich zwei plus eins, dann wird zuerst
der arathmetische Ausdruck ausgewertet und dann wird erst der Vergleich durchgeführt.
Das ist wieder eine Frage der Präzedenz.
Muss man halt wissen, wie das in der Programmiersprache funktioniert.
Dass man sich die Regeln halt genau angucken
Okay, eine Bulsche Literale,
das ist wieder so ein Spezialgebiet hier für die Informatiker,
sehr wichtig, Bulsche Aggebra,
vom Tybulien habe ich jetzt auch schon mal benutzt irgendwie,
Bulien, B, habe ich schon einen gehabt,
nee, habe ich noch nicht, Moment.
Eine Frage irgendwo? Da ist eine Frage. Bei der
ganzaligen Division wird es geruntert oder abgeschnitten. Ganz spannende Frage,
ja, also ganz zeitige Division, 20 durch 6,
ist 3, da wird ja erstmal möglicherweise,
wir können jetzt nochmal gucken, ein anderes Beispiel wäre 23 durch 6.
So 23 durch 6. Wenn da gründet würde,
könnte man vermuten, es ist eher an der 4 dran.
Wenn abgeschnitten wird, kommt eine 3 raus. Und es
kommt eine 3 raus. Es wird also tatsächlich abgeschnitten.
Also die ganzzeitige Division ist wirklich, wie oft passt das da rein?
Gut. Butsche Werte. Das Wichtigste ist erstmal,
es gibt Literale, nämlich True.
True is True und Falls is Falls. Toll. Die
kann ich so hinschreiben. Und sie tun das,
was man so erwartet
Was immer ganz schön ist,
man kann ja dann auch diese Bullshen-Dinger miteinander vergleichen.
Ich kann also tatsächlich auch zwei Bullshen-Variablen miteinander vergleichen.
Also ist die eine gleich der anderen. Das ist bei True
gleich gleich vorher ziemlich sinnlos. Und True ist sicherlich ungleich false.
Das ist alles, das ist alles so definiert.
Aber man kann natürlich dann sehr viel aufwendigere Ausdrücke haben.
Und das gucken wir uns jetzt ein bisschen genauer an.
Nämlich hier die Bullshen-Algebra. Kleiner Ausflug in die Bullshen-Algebra,
weil es einfach so wichtig ist für uns.
Nehmen wir mal an, ich habe so eine einfache Aussage,
wie ich habe Hunger
Das kann ich erst mal als Aussage treffen.
Der Wahrheitsgehalt, diese Aussage, ist fragwürdig. Das kann
richtig sein, das kann falsch sein. Ich kann also
tatsächlich mir jetzt hier eine Bullsche Variable definieren, hungrig.
Ungrecht ist, sagen wir mal, Falls zu Anfang.
So, habe ich also hier, hungrig, ich bin nicht hungrig.
Also, nein, die Aussage, ich bin hungrig, ist Fords.
Ich kann jetzt das negieren, ich kann sagen,
nicht hungrig, dann wird sozusagen diese Bullsche Aussage negiert.
Das Ergebnis ist dann True
Das ist aber komplett davon abhängig, wie denn die Belegung
vorher war, wenn die Aussage vorher falsch war,
es hier dann hinterher war und umgekehrt.
Also auch diese Aussage kann wahr oder falsch sein.
Aber die logische Negation ist auf jeden Fall immer das Gegenteil.
Zweite Aussage können sein, ich habe Durst und ich kann
dir jetzt zwei solcher Aussagen miteinander verknüpfen.
Ich kann ja sagen, ich habe Hunger und ich habe Durst.
Das interessiert euch wahrscheinlich ziemlich wenig. Aber man kann dann
das verwenden in Bedingungen und das werdet ihr relativ viel machen.
Also wenn ich Hunger und Durst habe,
dann nehme ich etwas zu mir
Gut, der eine oder andere wird sagen,
ich nehme auch was zu mir,
wenn ich nur hungrig bin oder nur durstig.
Also, wenn ich Hunger oder Durst habe, dann nehme ich
etwas zu mir. Und das ist dann die Dissunktion,
also eine Verknüpfung mit oder, wird Dissunktion genannt,
die Verknüpfung mit und wird Konjunkton genannt.
Das sind so die Begriffe, die ihr da braucht in
der Burschen Algebra. Wenn wir damit programmieren,
dann geben wir es mal auf so ein paar Sachen achten.
Also, wir haben das jetzt schon gesehen,
ich konnte jetzt hier einfach diese Bullshit-Variablen negieren.
Was ich immer wieder in Übung sehe,
ist zum Beispiel sowas IF,
hungrig,
gleich gleich true
Also, wenn die Variable hungrig, mit dem wir True
belegt ist, das ist ziemlich redundant. Das ist irgendwie,
dann soll er jetzt irgendwas machen, aber hungrig,
gleich gleich True, ist fort, in diesem Fall jetzt.
Ich kann auch schreiben, einfach stattdessen hungrig, ja, ist auch false.
Also der Vergleich einer Butschenvariablen mit True ist redundant.
Butsche Algera kann man wegkürzen sozusagen. Das steht aber ganz
oft im Quertext oder wenn ich schreiben will, if hungrig gleich gleich False.
Also wenn jemand irgendwie nicht hungrig ist, dann kann ich,
stattdessen kann ich auch beschreiben, if not hungrig.
Und das liest sich auch viel besser,
wenn denen die Bulschen Variablen gut benannt sind.
Deswegen geben wir immer den Hinweis,
wählt eure Bulschen Variablen danach aus, was sie aussagen sollen.
Gutes Beispiel ist hungrig, also wenn das True ist,
dann ist wohl jemand hungrig, aber das False ist wohl nicht.
Schlechtes Beispiel ist, in so einem Spiel hatten wir das mal,
so Ameisen laufen rum und haben eine Ausrichtung,
also wo sie bevorzugt hinlaufen nach links oder nach rechts.
Da hat man eine Bulsche Variable Ausrichtung.
So, was heißt jetzt True bei Ausrichtung?
Ist das jetzt links hinaus oder ist das ein Rechtshändler?
Wenn dir Bulsche Variable heißen würde, links hin händig,
dann weiß man, True heißt,
es ist ein Linksinner und Fords heißt es ein Rechtshänder.
Da ist eine Frage. Dadurch, dass man es im Kino schreibt,
ist es nicht expliziter oder wird dadurch das Ganze langen Körper?
Das muss der verlustige Außerarzt innere Landeninformationen,
die aber durchaus offen und nicht nachbar sind, aber ja.
Ja, also es ist einfach, es ist umständlicher zu lesen.
Es ist, nee, nee, da kann man drum streiten.
Also wenn ich da stehen habe, if hungrig,
finde ich das lesbarer. Wenn hungrig zutrifft, dann,
ich muss nicht noch diese relativ kryptischen Vergleich mit einer
bullschen Variablen machen.
Diese Variante ist die Steppenfree
Dann sollte sie treffend gewählt sein. Ah, sicher.
Das ist eine Bedingung dabei, genau. Deswegen sind die
ja dafür, dass ihr eure Bullshit-Variablen treffend benennt.
Das ist ja die Empfehlung. Aber tatsächlich ist das üblicherweise einfach redundant
und alles, was redundant ist, sollte eigentlich weg.
Es ist nicht unbedingt lesen, na gut,
man kann natürlich der Meinung sein, dass es lesbarer ist.
Ich will ja hier niemanden bevormunden. Unsere Quelltextkonventionen sagen eher
, lasst es weg. Okay, Bullshit Algebra,
primär für Ausdrücke interessant, also iFX-Größe 100,
dann mach irgendwas oder Wild X, kleiner 10,
mache irgendwas in einer Schleife.
Es gibt Bullshit-Literale, Bullshit-Variablen, Bullshit-Ergebnisprozeduren.
Also if Falls, Das ist zum Beispiel tatsächlich so,
diese Anweisung wird nie ausgeführt, weil Falls liefert immer Falls.
If versichert, schreibe Versicherungen an, If Admin-Rechne vorhanden.
Also das ist hier ein Methodenaufruf, der ein bulsches Ergebnis
liefert oder hier tatsächlich irgendwelche Verknüpfungen in irgendeinem Spiel.
Kollision und ich bin nicht gerade unverwundbar oder die Restzeit ist
gleich null, dann ist das Spiel zu Ende.
Solche Bedingungen gibt es halt relativ viele. Und was ihr
für die Bulsche-Argewalt brauchst und die Wahrheitstafeln, Negation,
klar, Negation von Falls is True, von True is
Falls, Konjunktion, Wartstabelle, Disfunktion,
das sind alles hier Beispiele mit solchen Literalen.
Das ist etwas, was universell ist,
völlig unabhängig von Java
Bulschal gebracht. Grundrechenregeln, auch hier Kommentativgesetz, assoziativgesetz,
distributivgesetz und die Demor ganzen Regeln, die sind ganz spannend,
die haben viele nicht so im Kopf.
Dabei auch immer darauf achten, not bin ich stärker als End- und All,
aber diese Demor-Gunschen Gesetze, die sind ganz lustig.
Also dieses Not-P oder Kuh ist das Gleiche wie Not-P and Not Kuh.
Also sozusagen, wenn ich das so ausmultipliziere, dann dreht
sich die Verknüpfung um. Also hier steht ein Ohr,
wenn ich das Ganze negiere,
dann werden die einzelnen Terminegiert und dazwischen kommt die Negation des des Operators,
der dazwischen stand, also aus dem Ohr wird ein End,
aus dem End wird ein Ohr.
Das ist unintuitiv und ist auch für viele überraschend.
Also wieder mal dieses Beispiel, was wir vorhin hatten.
Ich sage, ich kann nur arbeiten, wenn ich,
wenn es nicht der Fall ist, dass sich hungrig oder durstig bin.
Also nicht hungrig oder durstig. The Morgan sagt,
das kann ich irgendwie vereinfachen. Ich kann sagen,
das ist nämlich nicht hungrig und nicht durstig.
Dass die beiden Aussagen äquivalent sind, ist nicht unbedingt intuitiv erkennbar.
Deswegen können wir es einfach mal durchgehen, hungrig,
hier alle Möglichkeiten, Fords Fords True True,
nämlich verknüpft mit Durstig,
alle Kombinationen hier aufgeführt in der Tabelle
Das ist das Schöne bei der Bullschen Algebra, die ist komplett überschaubar.
Es sind nur zwei Werte und mit denen kann man irgendwie
so rumrechnen. Wenn ich jetzt sage hungrig oder durstig,
dann ist das hier die Verknüpfung, also Falls und dreimal True.
Wenn ich das dann insgesamt negiere, kommt da raus,
True und dreimal Falls. Das ist der obere Ausdruck.
Jetzt kann ich mir den unteren angucken, also wieder die
gleiche Ausgangstabelle, nicht hungrig, sieht dann so aus.
Das ist sozusagen eine Negation von dieser Spalte.
Dann kommt nicht durstig dazu, das ist eine Negation von
der Spalte. Und wenn ich das wiederum verknüpfe,
diese beiden hier miteinander verknüpfe mit und kommt das raus und
die sind gleich
Also die morgenannte Regeln sind ziemlich wichtig. Wir werden euch
ständig über den Weg laufen, wenn ihr so logische Ausdrücke vereinfachen wollt.
Fällt vielen Leuten schwer, unsere Erfahrung. Okay, Gleitkammerzahlen
, da habe ich jetzt schon ziemlich viel dazu gesagt.
Ich habe gesagt, lasst die Finger davon.
Jetzt ein bisschen konkreter, was ist in Java verbaut?
In Java ist der iTriple-E-Standard 7554 verbaut. Also das ist
das, was ich erwähnt habe. Auch der Goldberg hat
diesen iTriple-E-Standard beschrieben. Da gibt es zwei Zahlenformate,
einmal einfache Genauigkeit, 32 wird doppelte Genauigkeit, 64-Bit.
Single Precision und Double Precision
Das Witzige ist, der Itraple-E, dieses Format,
754 definiert Summen von zweier Potenzen. Wenn wir aber was hinschreiben,
wenn ich in Java was hinschreibe, sowas wie,
was ich gerade schon hatte, irgendwie fünf E-2,
kann ich hier vielleicht fünf E-2, das ist 500.
Das ist nämlich fünfmal 10 hoch 2. 10 hoch 2 ist
100, fünfmal, also das ist zur Basis C.
Das, was wir schreiben, ist zur Basis 10,
dummerweise aber intern ist es als Zweierpotenzen abgelegt.
Wenn man sich mit Mathematik gut auskennt, weiß man,
Zweiersystem und also das Thema zur Basis 2 und zur Basis 10
sind nicht 100 Prozent kompatibel.
Man kann nicht alles eindeutig aufeinander abbilden. Zum Beispiel 0,1
ist im Dezimalsystem ziemlich eindeutig abbildbar. Im Dualsystem gibt es
einen Bruch. Das ist irgendwie hier so eine Periode und
eine endliche Anzahl von Bits muss dann irgendwas abgeschnitten werden.
Das heißt, wenn ihr 0,1 ein paar Mal aufaddiert,
kommt da nicht unbedingt eins raus. Ein Problem von Gleitkammerzahlen
und dann noch dieses Problem mit den großen Zahlen.
Also ich kann das hier mal zeigen. 9,8,
7, 6, 5, 4, 3, 2,1,
habe ich ja gesagt, das ist eine ziemlich große Inzahl.
Jetzt kann ich da ein F dahinter schreiben,
dann soll es als Float aufgefasst werden
Da würde man es ja glauben, Gleitkammerzahlen können ja viel mehr größere Zahlen aufnehmen.
Dann kann der wahrscheinlich auch locker diese Zahl aufnehmen. Weit gefehlt,
wenn man da jetzt genau hinguckt, dann steht da 10 hoch 8,
10 hoch 8 und dann steht aber am Ende steht eine 3,4,
also 9, 8, 7, 6, 5,
4,3. Nicht 2, 1, sondern 3,4.
Also statt einer 21, am Ende steht eine 40 am Ende.
Das ist komisch. Wenn ich diesen Wert jetzt,
wenn ich da jetzt einen drauf addiere,
dann ändert sich nichts an der Zahl.
Ich kann da vielleicht 5 drauf addieren,
ändert sich nichts an der Zahl
Ich addiere auf eine Zahl was drauf und es tut sich nichts.
Okay, machen wir mal, dann nehmen wir mal zehn drauf.
Ändert sich nichts. Und dann nehme ich mal 20,
tut sich immer auch nichts. Dann nehme ich mal 40,
Moment, 40, 40, 40. 40 machen nichts.
Jetzt hat sich was getan. Genau. Ja, so habe ich
es auch eigentlich. Damit habe ich eigentlich gerechnet. Tatsächlich sieht man jetzt hier,
da ist jetzt irgendwie eine andere Zahl,
das ist jetzt irgendwie statt der 40 am Ende,
ist es jetzt hier irgendwie auch wieder eine 40,
aber eine 44. Vorher war es eine 3, 40,
das ist eine 44,
also relativ komisch
Das ist genau das, was ich sagen will.
Hier dieser Zahlenstrahl macht das deutlich. Wir sind einfach Sprünge drin.
Je weiter von der Null weg, desto größer sind die.
Und da sind ganze Zahlenbereiche, wo einfach Zahlen nicht darstellbar sind.
Und dann wird die nächsten Niere genommen. Also dann,
wenn man sagt, ich möchte gerne diese Zahl haben in der Lücke,
dann sagt er, das Zahlenformat, okay,
dann nehmen wir entweder die nächst kleinere oder die nächst größere,
je nachdem.
So, und dann können tatsächlich solche Additionseffekte auftreten, dass einfach Sachen verloren gehen.
Wenn man große Gleitkammer zahlen mit kleinen Gleitkammerzahlen, addiert,
kann es sein, dass die Kleine komplett verloren geht.
Das ist ein weites Feld, diese Gleitkammerzahlen,
da will ich nicht nur drauf eingehen.
Ich möchte aber jetzt noch auf Typumwandlung eingehen.
Das ist jetzt nochmal ein relativ wichtiger Punkt,
weil eben kam schon die Frage, was ist denn,
wenn ich sage,
in ears
gleich true
Es gibt einen Typfehler. Wissen wir. Schützt uns ja auch. Andererseits,
wenn ich sowas schreibe, wie Double D ist gleich 5,
also ich habe jetzt hier Double D ist gleich 5,
5, wissen wir ja inzwischen, ist ein Inliteral.
D ist ein Double. Jetzt wäre es ja blöd,
wenn der Compiler sagen würde, hey, du hast ja eine ganze Zahl,
das ist aber eine Gleitkammerzahl, passt nicht zusammen.
Nein, der Compiler ist da entspannt, weil er sagt,
die Intacher-Zahl kann ich in dem Double locker repräsentieren.
32 Bit Guns Komma, Ganzzahl kann ich locker in 64 Begleitkamera repräsentieren.
Da ist der also ganz entspannt, das heißt,
wenn ich jetzt hier tatsächlich in Simikonern davor schreibe,
dann hat D tatsächlich
den Wert
Das ist eine Zuweisung, die kann ich machen.
Das ist prima. Und das ist eben genau das,
was der Compiler macht. Er macht eine Typumwandlung.
Das heißt, tatsächlich wird dieses Bitmuster für die 5,
für die ganzzahlige 5 umgewandelt in das Bitmuster für die Gleitkomma 5.
Das ist also eine echte Typumwandlung. Da passiert richtig was
, da werden Bits verändert. Und da muss man eben
genau aufpassen, was wird in was umgewandelt.
Und in Java ist es einfach so,
wenn der Ziehtyp eine höhere Genauigkeit hat, als der Ausgangstyp,
ist alles gut, dann sagt der Compiler gerne.
Also zum Beispiel, was wir vorhin gesehen haben,
ich konnte ja in meinem In-E
ein Zeichen zuweisen
Dann wird tatsächlich das Zeichen umgewandelt in seiner Ordnungszahl im Zeichensatz.
Also zum Beispiel das große A, ist das 65. Zeichen,
also wird in dem I dann die 65 gespeichert. Was nicht geht,
ist andersrum, vielleicht können wir nochmal hier gucken,
hier finden jetzt mehrere Umwandlungen statt,
da könnt ihr ja vielleicht mal drüber nachdenken,
was hier das Ergebnis ist von dem, was hier so steht.
Ganz lustig, machen wir vielleicht hinterher nochmal. Was wichtig ist,
ist, dass es eben halt andersrum nicht geht.
Also wenn ich zum Beispiel sowas habe,
wie Inti ist gleich 3.1,4,5,
dann ist das hier ein Double und ein Double
kann ich nicht in einem In speichern
Dann sagt der Compiler, das darfst du nicht.
Also hier ein VI ist gleich, was habe ich da jetzt gesagt,
irgendwie 3.1, 4. Possible Loss of Precision required in, Founddouble.
So, wenn ich jetzt aber verdammt nochmal will,
dass der Compiler das macht, ich sage jetzt,
ich will jetzt wirklich das abschneiden, diese Nachkommastellen,
dann kann ich das machen.
Ich kann schreiben, I ist gleich int.
Stopp, gleich. Dann kann ich in Runden klammern,
hier reinschreiben, 3.1, 4. Im Moment, 3.1,
4. Das heißt,
dieses Double wird jetzt von mir als Programmierer gezwungen,
Couversion erzwingen,
reingezwungen in die 32-Bit
Und dann sagt er, gut,
das ist eine 3. Und wenn es jetzt ein 3,9 wäre,
dann würde er das auch abschneiden.
Das ist die Frage von eben gewesen. Er macht nur
eine 3 draus. Er schneidet also einfach ab.
Das ist dieses explizite Erzwingen, dass etwas umgewandelt wird.
Das nennen wir eine Typumwandlung mit diesen runden Klammern hier.
Häufig gemachter Fehler, ist das hier, Float F ist
gleich 3,1415. Warum ist das ein Problem?
Float F hier mit diesem Dings, wer hat aufgepasst?
Warum ist das ein Problem? Warum will der Compiler
da meckern? Ich meine jetzt auf kurz,
kriegt das er
Genau, also das, es fehlt das F, kann man sagen,
also das hier ist ein Double und das ist ein Float ist 32 Bit.
Das heißt, man versucht 64 Bitgenauigkeit in 32 Bit zu speichern,
da meckert der Compiler. Possibledoes of Precision. Okay,
das nur nochmal, dass ihr einfach wisst,
dass zwischen diesen Zahlenformaten und auch zwischen Char und Int-Umwandlung mit sind.
Wenn ich zum Beispiel sowas habe, wie,
ich hatte gerade diesen Char hier,
das ist das B, wenn ich jetzt sage,
I ist gleich dieser Char, dann ist I 66.
Wenn ich jetzt sage, Char ist gleich Char plus 2,
dann meckert er. Weil nämlich Charplos 2 liefert ein Int,
32 Bit, ein Char hat aber nur 16 Bit.
Deswegen sagt er, nun kriege ich da nicht rein.
Auch da kann ich jetzt wieder mit einer Typzusicherung an deren Dashball sagen,
mach bitte eine Typumwandlung. Okay, das war das,
dass die Übersicht, die primitiven Typen jetzt zum Schluss nochmal,
na Moment, ein bisschen Sturesi, juhu,
eine kleine Abstimmung.
Mal nochmal sehen, ob ihr auch jetzt aufgepasst habt
Welchen Wert hat der folgende Java-Ausdruck? Ja,
da steht also fünf durch zweimal drei und er kann jetzt
als mögliche einfach gegeben werden,
null oder sechs oder 7,5 oder
Okay, ich glaube, das reicht erstmal,
so über 250 Stimmen, oh, jetzt geht es nochmal richtig ab.
Ich beende die Abstimmung. Ich zeige mal die Verteilung der Antworten.
Ja, würde ich gerne zeigen. Das scheint nicht zu
funktionieren. Das erste Mal, dass Sturissi Sorgen macht.
Okay. Die richtige Antwort ist 6. Ja,
das ist nämlich eine ganz zeitige Division hier
Okay, nehmen wir den nächsten. Was ist das denn
hier? Oh, ich starte erstmal die Abstimmung, sorry.
Okay, zweieinhalb Stimmen sind erreicht, sehr schön,
ich breche es ab und jetzt gucken wir,
ob wir hier übrigens was zu sehen bekommen.
Ja, so, 25 ist die richtige Antwort,
mal gucken, 25 Ah, mal gucken.
Ja, das ist richtig. Das haben ziemlich viele richtig,
sehr schön. Mal gucken, ob er das jetzt hier auch hinkriegt.
Bei eins, nee. Irgendwas ist bei eins faul.
Dann schalten wir den mal wieder weg hier und den auch wieder
weg. Die nächste. Was ist denn das hier?
Dieser Java-Ausdruck. Das sind alles mehr oder weniger Klausuraufgaben
Ja, so bei 200 Stimmen werde ich dann
auch mal aufhören. Ja, das sieht gut aus.
Sehr schön. Ich, oh ja, 300 Stimmen toll.
Also sind doch mehr Leute hier, als ich dachte.
Sehr schön. Oh, 370. Was ist hier los?
Die Zuschauer draußen an den Bildschirmen auch dabei.
400 Stimmen. So, jetzt ist Schloss.
Gut. Gucken wir mal auf die Verteilung.
Also relativ viele sagen null
Einige sagen 17, die richtige Antwort ist 17. Ziemlich viele
Leute haben sich da wohl vertan. Oder haben gar nicht
richtig mit Ahrtag mit abgestimmt. Das kann natürlich auch sein.
Dann, wie viele Typummandlungen finden in dieser Java-Anweisung statt?
Letzte Frage für heute. Ich starte die Abstimmung.
Wenn ihr diesen Ausdruck jetzt sozusagen nach und nach auswertet,
ihr müsst euch überlegen,
wie das wohl ausgewertet wird,
in welcher Reihenfolge und wann da
jeweils irgendwelche Umwandlungen stattfinden
Ja. Ich sehe gerade, ich habe da die falsche
richtige Antwort gewählt. Okay, was werden wir gleich sehen?
Gut, wir sind wieder bei über 400 Stimmen.
Ich halte das an. Gucken wir mal erst mal auf
die Verteilung. Ziemlich viele sagen, es sind drei.
Ziemlich viele sagen, es ist nur eine einzige Umwandlung
Richtige Antwort ist falsch, ich habe mich vertan.
Es sind tatsächlich drei. Ich kann das nochmal zeigen.
3 plus 4, damit das der Char umgewandelt in
einen innt, dann ist das ein Int-Ausdruck.
Dann wird hier ein Int und ein Float irgendwann,
das heißt, da wird der Int umgewandelt in einen Float,
damit die miteinander umgerechnet werden können.
Dann hat man hier einen Float-Ausdruck insgesamt und das wiederum wird umgerennt,
damit es in einen Double umgerechnet werden kann.
Also es sind drei Konvertierungen dabei und ich habe einfach
nur die falsche richtige Antwort gegeben.
So, dann vielen Dank für heute.