Bitweise Operatoren
Zweierkomplementdarstellung
Bitweise Operatoren können in Java ausschleißlich auf numerische Operanden, sprich alle numerischen Datentypen, angewendet werden. Um die bitweisen Operatoren zu erklären verwenden wir hier den Datentyp byte.
Numerische Datentypen werden in Java binär und als Zweierkomplement interpretiert. Das Zweierkomplement ist eine Möglichkeit, negative Zahlen im Binärsystem darzustellen, ohne zusätzliche Zeichen wie + und − zu benötigen.
Ist das höchstwertige Bit gesetzt (= 1), liegt eine negative Zahl vor.
Die Zweierkomplementdarstellung ist am einfachsten wie folgt zu erklären:
Alle Bits haben denselben Wert wie bei der positiven Darstellung. Das höchstwertige Bit hingegen ist negativ. Daher muss der Wert dieses Bits von dem Wert restlichen Bits abgezogen werden.
Schauen wir uns folgendes Beispiel an:
10000010
Das höchstwertige Bit ist eine 1, sprich es ist negativ. Statt für 128 steht es für -128.
Die restlichen Bits haben zusammen einen Wert von 2. Es ergibt sich folgende Rechnung: 2 - 128 = -126
In der Zweierkomplementdarstellung hat die oben abgebildete Bitfolge also den Wert -126.
Schau dir die Tabelle an. Dort findest du ein paar wichtige Zahlenwerte zur Veranschaulichung des eben erklärten:
| Binärwert |
Interpretation als |
Binärwert | Interpretation als Zweierkomplement |
Binärwert | Interpretation als Zweierkomplement |
Binärwert | Interpretation als Zweierkomplement |
|---|---|---|---|---|---|---|---|
| 00000000 | 0 | 01111110 | 126 | 10000000 | -128 | 11111110 | -2 |
| 00000001 | 1 | 01111111 | 127 | 10000001 | -127 | 11111111 | -1 |
| 10000010 | -126 |
Operatoren
Bitweise Operatoren werden in Java verwendet, um Binärwerte bitweise zu manipulieren. Die folgenden bitweisen Operatoren gibt es in Java:
- Einerkomplement-Operator
- Bitweise Logische Verknüpfungs-Operatoren
- Schiebe-Operator
Die folgende Tabelle stellt die bitweisen Operatoren von Java einzeln vor:
| Operator | Bezeichnung | Beispiel | Beschreibung |
|---|---|---|---|
| ~ | Einerkomplement | ~a | Es werden alle Bits von a invertiert, das heißt aus 0 wird 1 und umgekehrt. |
| & | Bitweises Und | a & b | Es wird a und b bitweise ausgewertet. Dabei wird jedes korrespondierende Bit von a und b miteinander Und-verknüpft. |
| | | Bitweises Oder | a | b | Es wird a und b bitweise ausgewertet. Dabei wird jedes korrespondierende Bit von a und b miteinander Oder-verknüpft. |
| ^ | Bitweises Exklusiv-Oder | a ^ b | Es wird a und b bitweise ausgewertet. Dabei wird jedes korrespondierende Bit von a und b miteinander Exklusiv-Oder-verknüpft. |
| << | Linksschieben | a << b | Es werden die Bits von a um b Positionen nach links geschoben. Auch das höchstwertige Bit wird nach links geschoben und erfährt keine besondere Behandlung. |
| >> | Rechtsschieben mit Vorzeichen (arithmetisch) |
a >> b |
Es werden die Bits von a um b Positionen nach rechts geschoben. Das höchstwertige Bit wird nach dem Schieben gesetzt, falls es auch vor dem Schieben gesetzt war. |
| >>> | Rechtsschieben ohne Vorzeichen (logisch) |
a >>> b |
Es werden die Bits von a um b Positionen nach rechts geschoben. Das höchstwertige Bit wird nach dem Schieben immer auf 0 gesetzt. |
In Processing kannst du dir eine Variable in binär anzeigen lassen mithilfe der binary() Funktion.
int wert = 3;
println(wert);
println(binary(wert));
3
00000000000000000000000000000011
binary() liefert dir einen String zurück! Du kannst sie also nicht verwenden, um eine Zahl in einer Binärzahl umzuwandeln. Es gibt auch das Gegenstück zu dieser Funktion: unbinary(). Diese Funktion nimmt einen Binär-String als Parameter und liefert einen Integer-Wert zurück.Ternärer Operator
Ein Operator mit drei Operandenstellen ist ein ternärer Operator. In Java gibt es genau einen ternären Operator, welcher deswegen auch der ternäre Operator genannt wird. Er ist der einzige Operator, der mit drei Operanden arbeitet und wird oft auch Bedingungsoperator genannt.
Der Bedingungsoperator hat folgenden allgemeinen Aufbau:
bedingung ? wert1 : wert2
→ bedingung muss immer ein boolescher Ausdruck sein. Er entscheidet über die Wertzuweisung. Ist er true , so wird der Wert nach dem Fragezeichen zugewiesen, ansonsten der Wert nach dem Doppelpunkt.
Die Variablenzuweisung erfolgt dann in der Form
variable = bedingung ? wert1 : wert2
Stell dir vor du schreibst ein Programm, das auswerten soll, ob Studierende eine Klausur bestanden haben. Bestanden haben sie, wenn sie mehr als 50 Punkte haben. Das sieht wiefolge aus:
int punkte = 76;
String msg = punkte >= 50 ? "Bestanden" : "Nicht bestanden";
println(msg);
Je nachdem, welchen Wert punkte hat, nimmt msg den Wert "Bestanden" oder "Nicht bestanden" an.
Rangfolge der Operatoren
Operatoren werden in Java nach einer festen Reihenfolge ausgewertet. Operatoren mit einem höheren Rang haben Vorrang vor Operatoren mit einem niedrigeren Rang. Dies wird auch als Vorrangregel oder Bindungsregel bezeichnet.
In Java hat jeder Operator eine gewisse Bindungskraft. Der Multiplikations-Operator hat z.B. eine höhere Bindungskraft als der Additions-Operator und wird somit zuerst ausgewertet. Ähnlich wie die Regel in Mathe: Punkt vor Strich.
Manchmal besitzen Operatoren die selbe Bindungskraft. In so einem Fall entscheidet die Assoziativität über die Reihenfolge der Auswertung. Der Additions– und Subtraktions-Operator haben z.B. die gleiche Bindungskraft. Werden sie aber in einer Kette von Additionen und Subtraktionen verwendet, bestimmt ihre Assoziativität über die Auswertungsreihenfolge. In diesem Fall sind beide Operatoren linksassoziativ, daher wird der Ausdruck von links nach rechts ausgewertet.
Daher wird a+b-c wie (a+b)-c ausgewertet und nicht wie a+(b-c).
In der folgenden Tabelle sind alle Java-Operatoren in Gruppen zusammengefasst.
Die Gruppenummer entspricht dem Rang des jeweiligen Operators. Gruppe eins enthält die Java-Operatoren mit dem höchsten Rang. Die Assoziativität gibt an, ob ein Operator von links nach rechts oder von rechts nach links ausgewertet wird.
| Gruppe | Operator | Beispiel | Bezeichnung | Assoziativität | Beschreibung |
|---|---|---|---|---|---|
| 1 | ++ -- |
a++ a-- |
Postinkrement Postdekrement |
Rechts | Beim Postinkrement wird dem übergeordneten Ausdruck der ursprüngliche Wert von a übergeben. Anschließend wird a um 1 erhöht. Beim Postdekrement wird dem übergeordneten Ausdruck der ursprüngliche Wert von a übergeben. Anschließend wird a um 1 verringert. |
|
++ |
++a --a |
Präinkrement Prädekrement |
Rechts | Beim Präinkrement wird dem übergeordneten Ausdruck der um 1 erhöhte Wert von a übergeben. Beim Prädekrement wird dem übergeordneten Ausdruck der um 1 verringerte Wert von a übergeben. |
|
| + - |
+a -a |
Positives/negatives Vorzeichen | Rechts | Nicht zwingend, da +a dem gleichen Wert wie a entspricht. Entspricht dem negativem Wert von a. |
|
| ~ | ~a | Einerkomplement | Rechts | Es werden alle Bits von a invertiert, das heißt aus 0 wird 1 und umgekehrt. | |
| ! | !a | Logisches Nicht | Rechts | Es wird a negiert. Ist a wahr, wird false zurückgegeben, andernfalls true. | |
| (type) | (int) a | Type-Cast | Rechts | Der Datentyp von a wird in den in Klammern angegebenen Datentyp umgwandelt. | |
| 2 | * / % |
a*b a/b a%b |
Multiplikation Division Modulo |
Links | Aus der Multiplikation von a mal b ergibt sich das Produkt. Aus der Division von a durch b ergibt sich der Quotient. Aus Modulo von a durch b ergibt sich der Rest. |
| 3 | + - |
a + b a – b |
Addition Subtraktion |
Links | Aus der Addition von a plus b ergibt sich die Summe. Aus der Subtraktion von a minus b ergibt sich die Differenz. |
| + | „A“ + b | String-Verkettung | Links | Ein String wird mit einem anderen String angefügt. Wenn nötig wird dabei der Wert in einen String umgewandelt. | |
| 4 | << | a << b | Linksschieben | Links | Es werden die Bits von a um b Positionen nach links geschoben. Auch das höchstwertige Bit wird nach links geschoben und erfährt keine besondere Behandlung. |
| >> | a >> b | Rechtsschieben mit Vorzeichen (arithmetisch) |
Links | Es werden die Bits von a um b Positionen nach rechts geschoben. Das höchstwertige Bit wird nach dem Schieben gesetzt, falls es auch vor dem Schieben gesetzt war. Somit bleibt eine negative Zahl auch nach dem Rechtsschieben negativ. | |
| >>> | a >>> b | Rechtsschieben ohne Vorzeichen (logisch) |
Links | Es werden die Bits von a um b Positionen nach rechts geschoben. Das höchstwertige Bit wird nach dem Schieben immer auf 0 gesetzt. | |
| 5 | < > |
a < b a > b |
Kleiner als Größer als |
Links | Es wird a mit b verglichen. Ist a kleiner als b wird true zurückgegeben, andernfalls false. Es wird a mit b verglichen. Ist a größer als b wird true zurückgegeben, andernfalls false. |
| <= >= |
a <= b a >= b |
Kleiner gleich Größer gleich |
Links | Es wird a mit b verglichen. Ist a kleiner als oder gleich b wird true zurückgegeben, andernfalls false. Es wird a mit b verglichen. Ist a größer als oder gleich b wird true zurückgegeben, andernfalls false. |
|
| 6 | == | a == b | Gleich | Links | Es wird a mit b verglichen. Ist a gleich b wird true zurückgegeben, andernfalls false. Wenn a und b Referenztypen sind, wird verglichen ob beide Variablen auf das gleiche Objekt referenzieren. Falls ja, wird true zurückgegeben. |
| != | a != b | Ungleich | Links | Es wird a mit b verglichen. Ist a ungleich b wird true zurückgegeben, andernfalls false. Wenn a und b Referenztypen sind, wird verglichen ob beide Variablen auf verschiedene Objekte referenzieren. Falls ja, wird true zurückgegeben. | |
| 7 | & | a & b | Und (bitweise) | Links | Es wird a und b bitweise ausgewertet. Dabei wird jedes korrespondierende Bit von a und b miteinander Und-verknüpft. |
| & | a & b | Und (logisch) | Links | Es wird a und b ausgewertet. Sind beide wahr, wird true zurückgegeben, andernfalls false. | |
| 8 | ^ | a ^ b | Exklusiv-Oder (bitweise) | Links | Es wird a und b bitweise ausgewertet. Dabei wird jedes korrespondierende Bit von a und b miteinander Exklusiv-Oder-verknüpft. |
| ^ | a ^ b | Exklusiv-Oder (logisch) | Links | Es wird a und b ausgewertet. Besitzt a einen anderen Wahrheitswert als b wird true zurückgegeben, andernfalls false. | |
| 9 | | | a | b | Oder (bitweise) | Links | Es wird a und b bitweise ausgewertet. Dabei wird jedes korrespondierende Bit von a und b miteinander Oder-verknüpft. |
| | | a | b | Oder (logisch) | Links | Es wird a und b ausgewertet. Ist mindestens einer der beiden Ausdrücke wahr, wird true zurückgegeben, andernfalls false. | |
| 10 | && | a && b | Und (S-C-E) | Links | Es wird a und b ausgewertet. Die Auswertung wird abgebrochen wenn a bereits falsch ist. Dann wird sofort false zurückgegeben. Sind beide wahr, wird true zurückgegeben, andernfalls false. |
| 11 | || | a || b | Oder (S-C-E) | Links | Es wird a und b ausgewertet. Die Auswertung wird abgebrochen wenn a bereits wahr ist. Dann wird sofort true zurückgegeben. Ist mindestens einer der beiden Ausdrücke wahr, wird true zurückgegeben, andernfalls false. |
| 12 | ?: | c ? a:b | Bedingte Auswertung | Rechts | Falls die Bedingung c wahr ist, wird der Wert von a zurückgegeben. Andernfalls, wird der Wert von b zurückgegeben. |
| 13 | = | a = b | Einfache Zuweisung | Rechts | Es wird a der Wert von b zugewiesen und b als Rückgabewert geliefert. |
| += -= *= /= %= |
a += b a -= b a *= b a /= b a %= b |
Additions-zuweisung Subtraktions-zuweisung Multiplikations-zuweisung Divisions-zuweisung Modulo-zuweisung |
Rechts | Es wird a das Ergebnis aus a + b zugewiesen und a + b als Rückgabewert geliefert. Es wird a das Ergebnis aus a – b zugewiesen und a – b als Rückgabewert geliefert. Es wird a das Ergebnis aus a * b zugewiesen und a * b als Rückgabewert geliefert. Es wird a das Ergebnis aus a / b zugewiesen und a / b als Rückgabewert geliefert. Es wird a das Ergebnis aus a % b zugewiesen und a % b als Rückgabewert geliefert. |
|
| &= |= |
a &=b a |= b |
Und-Zuweisung Oder-Zuweisung |
Es wird a das Ergebnis aus a & b zugewiesen und a & b als Rückgabewert geliefert. Es wird a das Ergebnis aus a | b zugewiesen und a | b als Rückgabewert geliefert. |
||
| <<= | a <<= b | Linksschiebe-Zuweisung | Es wird a das Ergebnis aus a << b zugewiesen und a << b als Rückgabewert geliefert. | ||
| >>= | a >>= b | Rechtsschiebe-Zuweisung mit Vorzeichen | Es wird a das Ergebnis aus a >> b zugewiesen und a >> b als Rückgabewert geliefert. | ||
| >>>= | a >>>= b | Rechtsschiebe-Zuweisung ohne Vorzeichen | Es wird a das Ergebnis aus a >>> b zugewiesen und a >>> b als Rückgabewert geliefert. |
Zusammenfassung
- Binäre Zahlen werden in Java als Zweierkomplement interpretiert. Dies ist eine Schreibweise, bei der das höchstwertige Bit genutzt wird, um darzustellen, ob es sich um eine negative oder eine positive Zahl handelt.
- Bitweise Operatoren rechnen mit und verarbeiten Binärzählen. Es gibt in Java 7 bitweise Operatoren:
- Einerkomplement: ~
- Bitweises Und: &
- Bitweises Oder: |
- Bitweises Exklusiv-Oder: ^
- Linksschiebung (arithmetisch): <<
- Rechtschiebung (ohne Vorzeichen): >>
- Der Ternäre Operator ist der sogenannte Bedinungsoperator. Mit ihm kann man eine Bedinung prüfen und je nach Ergebnis einer Variablen einen Wert zuweisen.
variable = bedingung ? wert1 : wert2
- Operatoren haben in Java eine Rangfolge, die entscheidet, welcher Operator zuerst angewendet wird.
- Es gibt zwei wichtige Faktoren, welche über die Rangfolge entscheiden: Zuerst die Bindungskraft und danach die Assoziativität (Richtung).