In der heutigen Lektion machen wir uns mit bitweisen Operatoren in Java vertraut und sehen uns Beispiele an, wie wir mit ihnen arbeiten können. Mit dem Wort „Bit“ bist du wahrscheinlich vertraut. Wenn nicht, sehen wir uns noch einmal an, was es bedeutet :)
Ein Bit ist die kleinste Informationseinheit in einem Computer. Der Name kommt vom englischen Ausdruck „binary digit“ (binäre Ziffer). Ein Bit kann durch eine von zwei Zahlen ausgedrückt werden: 1 oder 0. Es gibt ein spezielles binäres Zahlensystem, das auf Einsen und Nullen basiert.
Wir wollen uns hier nun nicht in einen mathematischen Dschungel begeben. Wichtig ist nur, dass jede Zahl in Java in die binäre Form umgewandelt werden kann. Dazu musst du die Wrapper-Klassen verwenden.
So kannst du das zum Beispiel für ein int machen:
Alle Operationen werden von links nach rechts ausgeführt, wobei ihre Rangfolge berücksichtigt wird.
Wenn wir zum Beispiel schreiben
public class Main {
public static void main(String[] args) {
int x = 342;
System.out.println(Integer.toBinaryString(x));
}
}
Konsolenausgabe:
101010110
1010 10110 (ich habe das Leerzeichen eingefügt, damit es leichter zu lesen ist) ist die Zahl 342 im Dezimalsystem. Wir haben diese Zahl in einzelne Bits unterteilt: Nullen und Einsen. Operationen, die mit Bits durchgeführt werden, nennt man bitweise.- ~ – bitweises NICHT.
101010110 ist 342, dargestellt als Binärzahl
010101001 ist der Wert des Ausdrucks ~342
Lass uns versuchen, das in die Praxis umzusetzen:
public class Main {
public static void main(String[] args) {
int x = 342;
System.out.println(~x);
}
}
Konsolenausgabe:
169
169 ist unser Ergebnis(010101001) im bekannten Dezimalsystem :)- & – bitweises UND.
277 wird als Binärzahl als 110110000 dargestellt
432 wird als Binärzahl als 1000101011 dargestellt
Als nächstes vergleicht der Operator & das erste Bit der oberen Zahl mit dem ersten Bit der unteren Zahl. Da dies ein UND-Operator ist, ist das Ergebnis nur dann 1, wenn beide Bits 1 sind. In allen anderen Fällen ist das Ergebnis 0.
100010101
&
110110000
_______________
10001000 – Ergebnis des &-Operators
Zuerst vergleichen wir die ersten Bits der beiden Zahlen, dann die zweiten Bits, dann die dritten und so weiter.
Wie du siehst, sind nur in zwei Fällen die beiden entsprechenden Bits in den Zahlen gleich 1 (das erste und das fünfte Bit). Alle anderen Vergleiche ergaben 0en.
Am Ende haben wir also die Zahl 10001000. Im Dezimalsystem entspricht sie der Zahl 272. Überprüfen wir das:
public class Main {
public static void main(String[] args) {
System.out.println(277&432);
}
}
Konsolenausgabe:
272
- | – bitweises ODER.
public class Main {
public static void main(String[] args) {
System.out.println(277|432);
}
}
Konsolenausgabe:
437
Wir haben alles richtig berechnet! :)- ^ – bitweises XOR (exklusives ODER)
public class Main {
public static void main(String[] args) {
System.out.println(277^432);
}
}
Konsolenausgabe:
165
Super! Alles ist so, wie wir es uns vorgestellt haben :)
Jetzt ist es an der Zeit, dich mit den Operatoren zum Verschieben von Bits vertraut zu machen.
Der Name spricht für sich selbst. Wir nehmen eine Zahl und verschieben ihre Bits nach links oder rechts :) Mal schauen, wie das aussieht:
Nach links schieben
Eine Verschiebung von Bits nach links wird angezeigt durch << Hier ist ein Beispiel:
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 3;// Shift distance
int z = (x << y);
System.out.println(Integer.toBinaryString(x));
System.out.println(Integer.toBinaryString(z));
}
}
In diesem Beispiel wird die Zahl x = 64 als Wert bezeichnet. Es sind die Bits des Wertes, die wir verschieben werden. Wir verschieben die Bits nach links (das hast du vielleicht anhand der Richtung des <<-Operators schon erraten).
Im Binärsystem ist die Zahl 64 = 1000000
Die Zahl y = 3 wird als Verschiebedistanz bezeichnet. Die Verschiebedistanz gibt an, um wie viele Bits du die Bits der Zahl xnach rechts/links verschieben willst.
In unserem Beispiel verschieben wir sie um 3 Bits nach links.
Um den Veränderungsprozess deutlicher zu sehen, schau dir das Bild an.
In diesem Beispiel verwenden wir int-Werte. Int-Werte belegen 32 Bit im Speicher des Computers. So sieht unsere ursprüngliche Zahl 64 aus:
Und jetzt nehmen wir jedes unserer Bits und verschieben es buchstäblich um 3 Stellen nach links:
Sieh dir an, was wir jetzt haben. Wie du siehst, sind alle unsere Bits verschoben und weitere 3 Nullen wurden am Rand eingefügt. Drei, weil wir um 3 Stellen verschoben haben. Hätten wir um 10 Stellen verschoben, wären 10 Nullen eingefügt worden.
Der Ausdruck x << y bedeutet also „verschiebe die Bits der Zahl x um y Stellen nach links“. Das Ergebnis unseres Ausdrucks ist die Zahl 1000000000, die im Dezimalsystem 512 ist.
Überprüfen wir das:
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 3;// Shift distance
int z = (x << y);
System.out.println(z);
}
}
Konsolenausgabe:
512
Absolut korrekt!
Theoretisch könnten die Bits endlos verschoben werden, aber da unsere Zahl ein int ist, haben wir nur 32 Binärstellen zur Verfügung. Davon sind 7 bereits von 64 (1000000) besetzt.
Wenn wir also 27 Stellen nach links verschieben würden, würde unsere einzige 1 über den Bereich des Datentyps hinausgehen und verloren gehen.
Es würden nur Nullen übrig bleiben!
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 26;// Shift distance
int z = (x << y);
System.out.println(z);
}
}
Konsolenausgabe:
0
Wie erwartet, hat sich die 1 über die 32 verfügbaren Bits hinaus bewegt und ist verschwunden. Am Ende haben wir eine 32-Bit-Zahl, die nur aus Nullen besteht.
Das entspricht natürlich der 0 im Dezimalsystem.
Hier ist eine einfache Regel, mit der du dir Verschiebungen nach links merken kannst:
Bei jeder Verschiebung nach links wird die Zahl mit 2 multipliziert.
Versuchen wir, den folgenden Ausdruck ohne Bilder von Bits zu berechnen
111111111 << 3
Wir müssen die Zahl 111111111 mit 2 multiplizieren. Als Ergebnis erhalten wir 888888888. Schreiben wir etwas Code und überprüfen das:
public class Main {
public static void main(String[] args) {
System.out.println(111111111 << 3);
}
}
Konsolenausgabe:
888888888
Nach rechts schieben
Diese Operation wird angegeben mit >>. Sie macht das Gleiche, nur in die andere Richtung! :) Wir werden das Rad nicht neu erfinden. Versuchen wir es mit demselben int 64.
public class Main {
public static void main(String[] args) {
int x = 64;//value
int y = 2;// Shift distance
int z = (x >> y);
System.out.println(z);
}
}
Durch die Verschiebung um 2 nach rechts geraten die beiden äußersten Nullen in unserer Zahl aus dem Bereich und gehen verloren. Wir erhalten 10000, was der Zahl 16 im Dezimalsystem entspricht
Konsolenausgabe:
16
Hier ist eine einfache Regel, um sich die Verschiebungen nach rechts zu merken:
Jede Verschiebung nach rechts dividiert durch zwei und verwirft den Rest.
Zum Beispiel bedeutet
35 >> 2
dass wir 35 zweimal durch 2 teilen müssen, wobei die Reste verworfen werden
35/2 = 17 (Rest 1 verwerfen)
17/2 = 8 (Rest 1 verwerfen)
Am Ende sollte 35 >> 2 gleich 8 sein.
Überprüfen wir das:
public class Main {
public static void main(String[] args) {
System.out.println(35 >> 2);
}
}
Konsolenausgabe:
8
Vorrang von Operatoren in Java
Beim Schreiben und Lesen von Code wirst du oft auf Ausdrücke stoßen, die mehrere Operationen kombinieren. Es ist sehr wichtig, dass du die Reihenfolge kennst, in der sie ausgeführt werden (sonst könnte dich das Ergebnis überraschen) Da es in Java viele Operationen gibt, wurde jeder von ihnen ein Platz in einer speziellen Tabelle zugewiesen:Operatorvorrang
Operatoren | Vorrang |
---|---|
Postfix | expr++ expr-- |
Unär | ++expr --expr +expr ~ ! |
Multiplikativ | * / % |
Additiv | + - |
Verschiebung | << >> >>> |
Relational | < > <= >= instanceof |
Gleichheit | == != |
Bitweises UND | & |
Bitweises exklusives ODER | ^ |
Bitweises inklusives ODER | | |
Logisches UND | && |
Logisches ODER | || |
Ternär | ? : |
Zuweisung | = += -= *= /= %= &= ^= |= <<= >>= >>>= |
int x = 6 - 4/2;
dann wird zuerst die Divisionsoperation (4/2) durchgeführt. Obwohl sie an zweiter Stelle steht, hat sie einen höheren Stellenwert.
Klammern geben den höchsten Vorrang an. Das kennst du wahrscheinlich noch aus der Schule.
Wenn du sie zum Beispiel zum Ausdruck
int x = (6 - 4)/2;
hinzufügst, dann wird die Subtraktion zuerst durchgeführt, da sie in Klammern eingeschlossen ist.
Der Vorrang des logischen &&-Operators ist eher niedrig (siehe Tabelle), daher steht er normalerweise an letzter Stelle.
So wie hier:
boolean x = 6 - 4/2 > 3 && 12*12 <= 119;
Dieser Ausdruck wird wie folgt ausgeführt:- 4/2 = 2
boolean x = 6 - 2 > 3 && 12*12 <= 119;
- 12*12 = 144
boolean x = 6 - 2 > 3 && 144 <= 119;
- 6-2 = 4
boolean x = 4 > 3 && 144 <= 119;
Als nächstes werden die Vergleichsoperatoren ausgeführt:- 4 > 3 = true
boolean x = true && 144 <= 119;
- 144 <= 119 = false
boolean x = true && false;
Und schließlich wird der UND-Operator (&&) zuletzt ausgeführt.
boolean x = true && false;
boolean x = false;
Zum Beispiel hat der Additionsoperator (+) einen höheren Vorrang als der Vergleichsoperator != (nicht gleich);
Daher wird in dem Ausdruck
boolean x = 7 != 6+1;
zuerst die Operation 6+1 ausgeführt, dann die Prüfung 7 != 7 (die zu false ausgewertet wird) und schließlich die Zuweisung des Ergebnisses (false) an die Variable x (die Zuweisung hat im Allgemeinen den niedrigsten Vorrang aller Operatoren; siehe die Tabelle).
Puh! Das war eine ganz schön umfangreiche Lektion, aber du hast es geschafft! Wenn du diese oder frühere Lektionen nicht ganz verstanden hast, mach dir keine Sorgen. Wir werden diese Themen in Zukunft noch öfter aufgreifen.
Ein paar CodeGym-Lektionen über logische und numerische Operationen. Dazu werden wir in nächster Zeit nicht kommen, aber es schadet nicht, wenn du sie jetzt schon liest.
GO TO FULL VERSION