13.2. Ausdrücke#
Im Vergleich zu natürlichen Sprachen, sind Programmiersprachen sind viel einfacher aufgebaut.
Entwickler*innen der Sprachen versuchen ihre Syntax so unmissverständlich, elegant, kurz und ausdrucksstark wie möglich zu gestalten.
In der Vergangenheit gelang das nicht immer und über die Jahre haben wir viel dazu gelernt.
In diesem Kurs verwenden wir Python
insbesondere deshalb, weil es eine der leserlichsten und zugleich mächtigsten Sprachen unserer Zeit ist.
Jedes Programm, bzw. jeder Algorithmus besteht aus vielen Ausdrücken. Ein Ausdruck beschreibt wie Daten (die Eingabe) verarbeitet werden sollen.
Die Multiplikation 3 * 5
ist beispielsweise ein Ausdruck der zwei Dezimalzahlen multipliziert.
Der Ausdruck besteht aus dem Symbol *
und zwei nummerischen Ausdrücken.
Die Multiplikation wird durch den Computer, genauer die CPU berechnet.
3 * 5
ergibt 15
.
3 * 5
15
Die Syntax einer Programmiersprache ist strikt.
Sie wird durch eine sog. Grammatik definiert.å
Zum Beispiel ist folgender Ausdruck fehlerhaft, da er nicht durch die Grammatik von Python
definiert ist.
Man sagt auch, dass die Sprache, welche durch die Grammatik definiert ist, den folgenden Ausdruck nicht enthält.
3 * * 5
Cell In[2], line 1
3 * * 5
^
SyntaxError: invalid syntax
Der Computer bzw. Python
-Interpreter weiß mit dieser Folge an Symbolen nichts anzufangen.
Wir werden vom Interpreter sachlich auf die mögliche Fehlerursache hingewiesen.
Bereits kleine Änderungen an der Syntax können zu einer neuen Bedeutung (Semantik) führen.
In Python
ist der Ausdruck
3 ** 5
243
syntaktisch korrekt. Seine Semantik ist die Berechnung von \(3^5\), was \(243\) ergibt. In kaum einer anderen Sprache gibt es für die Potenz eine derart kurze Schreibweise.
13.2.1. Arithmetische Operatoren#
Die Multiplikation *
wie auch die Potenz **
bezeichnen wir als arithmetische Operatoren, da sie numerische Werte (Zahlen) verarbeiten.
Es gibt jedoch noch eine ganze Reihe von weiteren arithmetische Operatoren:
Operator |
Beschreibung |
Beispiel |
Bedeutung |
---|---|---|---|
|
Addition |
|
\(3 + 4\) |
|
Subtraktion |
|
\(3 - 4\) |
|
Multiplikation |
|
\(3 \cdot 4\) |
|
Division |
|
\(3 / 4\) |
|
Potenzierung |
|
\(3^4\) |
|
ganzzahlige Division |
|
\(\left \lfloor{3/4}\right \rfloor\) |
|
Modulo |
|
\(10 - (4 \cdot \left \lfloor{10/4}\right \rfloor)\) |
Jeder dieser Operatoren op
erwartet zwei Zahlen, eine links und eine rechts von op
.
Die Bedeutung der Modulo-Operation %
sieht kompliziert aus, doch bedeutet dies schlicht, dass 10 % 4
der ganzzahlige Rest der Restwertdivision ist.
Die ganzzahlige Division rundet das Ergebnis der Division auf die nächst kleinere ganze Zahl (Integer). Beachten Sie
-2 // 3
-1
ergibt -1
und
2 // 3
0
ergibt 0
.
Arithmetische Operationen werden von der arithmetischen Einheit der CPU ausgewertet. Mit ihnen können wir numerische Gleichungen lösen aber auch Indices manipulieren.
13.2.2. Vergleichsoperatoren#
Objekte können über Vergleichsoperatoren miteinander verglichen werden.
Das Ergebnis ist ein boolscher Wert True
oder False
.
Operator |
Beschreibung |
---|---|
|
ist |
|
ist |
|
ist |
|
ist |
|
ist |
|
ist |
|
ist |
Erneut ist Python
hier ein wenig speziell, da es die mathematische Schreibweise \(0 < x < 5\) zulässt.
Dies erhöht die Lesbarkeit, da wir solche Verkettungen von Vergleichsoperatoren gewohnt sind.
5 < 7 < 10 # True
True
5 < 7 and 7 < 10 # True
True
5 < 7 < 5 # False
False
Vergleichsoperatoren können auch auf nicht-numerischen Werten (ganze Zahlen int
, Fließkommazahlen float
) definiert sein.
So können wir in Python
auch Zeichenketten str
mit den Vergleichsoperatoren lexikographisch vergleichen:
'Anna' < 'Emma' # True
True
Generell vergleichen wir Objekte einer Menge immer bezüglich einer (totalen) Ordnung.
Diese Ordnung muss irgendwo definiert worden sein, ob durch die Standardbibliothek von Python
, impliziet, oder durch uns Entwickler*innen.
13.2.3. Logische Operatoren#
Der obige Ausdruck ist aus weiteren Ausdrücken zusammengesetzt.
Er behinhaltet den Ausdruck and
, d.h., dem logischen UND (\(\land\)).
Dieser erwartet auf der linken und rechte Seite jeweils einen Wahrheitswert (boolschen Ausdruck).
Zum Beispiel, liefern Vergleichsoperatoren boolsche Ausdrücke zurück.
x = True
y = False
x and y
False
x and y
ergibt genau dann True
wenn die Auswertung von x
und y
jeweils True
ergeben.
Wir haben diese Operatoren bereits im Abschnitt Manipulation besprochen.
Sie werden in Computern durch Gatter realisiert.
Lassen Sie uns diese nochmals zusammenfassen:
Operator |
Beschreibung |
---|---|
|
ist |
|
ist |
|
ist |
13.2.4. Bitoperatoren#
Zur Vollständigkeit listen wir auch noch die sog. Bitoperatoren auf. Diese manipulieren ganze Zahlen in ihrer Binärdarstellung.
Erinnern Sie sich an den Abschnitt Repräsentation? Dort haben wir beschrieben wie schlussendlich jeder Wert, egal ob Zahl, Zeichen, Bild, Ton als Binärcode im Speicher liegt. Bitoperatoren nehmen diesen Binärwert und verarbeiten bzw. kombinieren ihn. Dabei wird jedes Bit des einen Werts mit dem Bit des anderen Werts kombiniert. Unsere Gatter aus dem Abschnitt Manipulation bilden den Grundstock für eine derartige Verarbeitung.
Python
bietet uns an diese maschinennahen Operationen auf Zahlen anzuwenden.
Zum Beispiel, kombinieren wir mit 5 & 4
jedes Bit der Zahl 5
mit dem and
der Zahl 4
.
Dies nennen wir das bitweise UND.
5 & 4
4
Jedes Bit der Zahl \(5_{10} = 0101_2\) und \(4_{10} = 0100_2\) wird durch eine AND-Gatter gejagt. Dies nennen wir auch bitweises UND der Binärzahlen \(0101_2\) und \(0010_2\):
Wenn Sie an dieser Stelle Probleme mit Binärzahlen haben, lesen sie Abschnitt Zahlen im Binärsystem. Folgende bitweisen Operationen stehen Ihnen in zur Verfügung:
Operator |
Beschreibung |
Beispiel |
Ergebnis |
---|---|---|---|
|
UND von |
|
|
|
ODER von |
|
|
|
exklusives ODER von |
|
|
|
Bitverschiebung von |
|
|
|
Bitverschiebung von |
|
|
Weshalb ist 10 ^ 3
gleich 9
?
Die ^
-Operation steht für das sog. exklusive ODER gesprochen entweder oder.
Das exklusive oder \(x \oplus y\) ergibt 1 genau dann wenn entweder \(x\) oder \(y\) (nicht aber beide) gleich 1 sind.
Es gilt \(10_{10} = 01010_2\) und \(3_{10} = 00011_2\).
Für ganze Zahlen entspricht die Bitverschiebung um ein Bit nach links der Multiplikation mit 2.
Die Verschiebung um ein Bit nach rechts, hingegen der ganzzahligen Division mit 2.
Deshalb ist 8 << 3
gleich
und 8 >> 2
gleich