&-Operator in diesem Zusammenhang

wolfgang12

Mitglied
Hallo,

ich verstehe hier in diesem Code-Schnippsel den "UND-Operator" nicht ('&').

Java:
static int isLastBitSet(int i){
		switch  ( i & 1 ){ // --> Was macht hier das '&'
		case 0: return 0;
		case 1: return 1;
		default: return 2;  //Nur weil das Prog sonst nicht kompiliert werden kann
		}
		
	}


Ich weiß, dass per UND-Operator ausdrücke logisch verknüpft werden können. Bei und müssen halt beide "Seiten" true ergeben damit auch das ergebnis true ist. Aber hier wird ja nichts ausgewertet. Das verstehe ich nicht. ;(



Vielen Dank :D
 

Haave

Top Contributor
Mit booleschen Ausdrücken hat das
Code:
&
hier nichts zu tun. Es ist ein Bit-Operator, der von deinem
Code:
int i
das letzte Bit umkippen lässt (im Binärsystem, also 1 wird zu 0 und 0 wird zu 1).

Ich bin mir nicht ganz sicher, da ich das selbst erst vor kurzem kennen gelernt habe, deshalb hoffe ich, jetzt nicht allzu viel Mist verzapft zu haben…
 

XHelp

Top Contributor
[EDIT]falsch gelesen - teil gelöscht[/EDIT]
0&egal ist immer 0
Du hast z.B. Zahlen
01010101111101 &
00000000000001
Alle bis auf die 1. Stelle werden automatisch 0. Wenn die 1. Stelle von deinem i 0 ist, dann ist das Resultat 0, ansonsten ist das Resultat 1
 

diggaa1984

Top Contributor
ist java in dem fall so schlau und prüft wirklich nur das letzte bit, oder macht es unsinnigerweise noch den check auf dem rest von i, was ja unnötig wäre?!
 

Antoras

Top Contributor
ist java in dem fall so schlau und prüft wirklich nur das letzte bit, oder macht es unsinnigerweise noch den check auf dem rest von i, was ja unnötig wäre?!
Ich versteh deine Frage nicht ganz. Java überprüft da gar nichts. Das macht die ALU in deiner CPU. Und wie die das macht musst du den Fragen, der die CPU entwickelt hat...
 

Jay_030

Aktives Mitglied
Hallo,

ich verstehe hier in diesem Code-Schnippsel den "UND-Operator" nicht ('&').

Java:
static int isLastBitSet(int i){
		switch  ( i & 1 ){ // --> Was macht hier das '&'
		case 0: return 0;
		case 1: return 1;
		default: return 2;  //Nur weil das Prog sonst nicht kompiliert werden kann
		}
		
	}
Die Methode macht, was ihr Name vermuten lässt: Gibt true zurück, wenn das letzte Bit bei i gesetzt ist. Aber da ich dieses grausame switch-Statement nicht sehen kann, hier nochmal in einer Zeite, "ordentlich" ^^:

Java:
public static boolean isLastBitSet(int i) {
    return (i & 1) == 1;
}
Finde ich lesbarer und eindeutiger. :)
 

Ruzmanz

Top Contributor
Anmerkung:
Ein Bit kann nur eine 1 oder eine 0 sein. Desshalb ist eine Switch-Anweisung eigentlich fehl am Platz. Du solltest lieber eine If-Abfrage benutzten. Bzw. die Lösung von Galileo Computing ist auch nicht schlecht.
 

Ark

Top Contributor
ist java in dem fall so schlau und prüft wirklich nur das letzte bit, oder macht es unsinnigerweise noch den check auf dem rest von i, was ja unnötig wäre?!
Definiere "Rest". Warum sollte denn bei & etwas komplizierter kompiliert werden, als es ist? Welchen Teil von & sollte denn die VM (und noch wichtiger: die "echte" CPU) nicht verstehen?

Deine darauffolgende Fragestellung hat damit aber wahrscheinlich nichts mehr zu tun. Präzisiere dich!

Ark
 

diggaa1984

Top Contributor
Definiere "Rest". Warum sollte denn bei & etwas komplizierter kompiliert werden, als es ist? Welchen Teil von & sollte denn die VM (und noch wichtiger: die "echte" CPU) nicht verstehen?

Deine darauffolgende Fragestellung hat damit aber wahrscheinlich nichts mehr zu tun. Präzisiere dich!

Ark



es geht mir darum:
i = 11000100001010101

wenn ich nun i & 1 auswerten lasse wäre es ja unsinnig überhaupt die anderen Stellen mit Ausnahme des ersten Bits zu prüfen. Bei ner dynamischen Variable i, welche den Inhalt zur Laufzeit ändert, kann der Compiler nicht zaubern. Aber wenn i bereits zur Compilezeit feststeht, wird da vielleicht intelligenter agiert?
Es ist eh ein unerheblicher Teil an Zeit, welchen man da einsparen könnte, aber die Frage schoss mir durch den Kopf und ich dacht, vielleicht kennt jemand die Verfahrensweise :)
 

Ruzmanz

Top Contributor
Java prüft überhaupt nichts. Das ist eine Operation wie Addieren und Subtrahieren. Entweder habe ich deine Frage falsch verstanden oder du weist nicht genau wie Bitweisen-Operatoren funktionieren.

Code:
 101010101010101 -> Irendeine Zahl
&000000000000001 -> Entspricht int i = 1
 000000000000001 -> Enstpricht int i = 1 (Ergebnis) (ist aber kein boolischer Wert)

Das wäre so als würde folgender Quelltext dort stehen:

switch(i - 244)
 
Zuletzt bearbeitet:

Illuvatar

Top Contributor
Anders gesagt: Der Prozessor schafft [c]a & b[/c] in einem Prozessorzyklus, egal was in a oder b drinsteht (ok kommt evtl auf den Prozessor an, ich weiß es nicht 100%, aber ich denk man kann es sich so vorstellen... ;)).

Wenn beide Variablen schon zur Compile-Zeit feststehen, dann kann es sein dass der Compiler gleich schon das Ergebnis hinschreibt. Aber das ist wohl eher nicht der Normalfall...
 

Antoras

Top Contributor
Wenn beide Variablen schon zur Compile-Zeit feststehen, dann kann es sein dass der Compiler gleich schon das Ergebnis hinschreibt. Aber das ist wohl eher nicht der Normalfall...
Ich hätte jetzt genau das Gegenteil behauptet. Wenn zur Compilezeit schon festgestellt werden kann, dass eine Rechnung unnötig ist, warum sollte der Compiler sie dann nicht durch das Ergebnis ersetzen?
Ich hab das mal beim GCC ausprobiert. Der hat tatsächlich alle Berechnungen, die auf statischen Variablen beruhten wegoptimiert. Im Asm-Code wurden nur noch die Ergebnisse der Rechnung in die Register geladen, die Rechnung selber wurde aber nicht mehr ausgeführt. Ich hab aber keine Ahnung in wie weit der JIT-Compiler der JVM da optimiert.
 

Illuvatar

Top Contributor
Ich hätte jetzt genau das Gegenteil behauptet. Wenn zur Compilezeit schon festgestellt werden kann, dass eine Rechnung unnötig ist, warum sollte der Compiler sie dann nicht durch das Ergebnis ersetzen?
Ich hab das mal beim GCC ausprobiert. Der hat tatsächlich alle Berechnungen, die auf statischen Variablen beruhten wegoptimiert. Im Asm-Code wurden nur noch die Ergebnisse der Rechnung in die Register geladen, die Rechnung selber wurde aber nicht mehr ausgeführt. Ich hab aber keine Ahnung in wie weit der JIT-Compiler der JVM da optimiert.

Ups, ich meinte: dass beide Variablen schon feststehen ist eher nicht der Normalfall. ;)
 

Ark

Top Contributor
@diggaa1984: Also, das ist so:

Der Bytecode-Compiler (das Ding, das aus java-Dateien class-Dateien macht) kompiliert für die Java VM. Diese virtuelle Maschine hat einen virtuellen Prozessor, so wie auch jede reale Maschine einen realen Prozessor hat. Und so ein Prozessor (egal ob real oder virtuell) hat einen bestimmten Befehlssatz. Gerade dieser Befehlssatz ist ein sehr wesentliches Unterscheidungsmerkmal bei Prozessoren.

Java erreicht die Plattformunabhängigkeit unter anderem dadurch, dass eben nicht für einen real existierenden Prozessor kompiliert wird, sondern nur für einen virtuellen (nämlich den der VM). Ein Compiler muss sich immer auf eine bestimmte Zielsprache einstellen bzw. ist allein dafür geschaffen worden, Quelltexte einer ganz bestimmten Sprache in die Sprache eines bestimmten Prozessors zu übersetzen.

Da der Bytecode-Compiler als Zielsprache die des virtuellen Prozessors hat, kann er auch nur in Befehle übersetzen, die für diesen virtuellen Prozessor verfügbar sind. Ob da Befehle zum Überprüfen einzelner Bits zur Verfügung stehen, kann ich gerade nicht sagen, halte ich aber für eher unwahrscheinlich. Das muss aber noch gar nicht so viel sagen.

Denn zur Laufzeit muss noch ein JIT-Compiler oder Interpreter ran. Der Interpreter ist im Wesentlichen eine Schleife, die entsprechend dem aktuellen Befehlscode ein Stückchen nativen Code aufruft, der dann ausgeführt wird. Der JIT-Compiler erkennt genauso die Befehle wie der Interpreter, führt sie aber nicht sofort aus, sondern schreibt sie sich vielmehr erst einmal auf. Wenn dann der Compiler genügend Code aufgeschrieben hat, ist er möglicherweise in der Lage, größere Zusammenhänge zwischen kleinen Codestückchen zu finden, und kann dann Optimierungen vornehmen.

Aber auch hier ist wieder einmal der Compiler an die Zielsprache gebunden. Wenn also der Befehlssatz des realen Prozessors einen Befehl kennt, um einzelne Bits zu prüfen, dann kann(!) der Compiler eventuell auf die Idee kommen, tatsächlich auch diesen Befehl dann, wenn es angebracht ist, einzusetzen.

Solche Optimierungen zur Laufzeit kosten zunächst einmal Zeit, denn es muss erst einmal kompiliert werden (vom Befehlssatz des virtuellen Prozessors zum Befehlssatz des realen Prozessors). Das erhöht die Latenz, aber auch die Geschwindigkeit.

Der Bytecode-Compiler erzeugt Code für einen virtuellen Prozessor, dessen Arbeitsweise eher an Stackmaschinen erinnert. Der JIT-Compiler dagegen muss diesen Bytecode in die Maschinensprache des realen Prozessors übersetzen. Dieser reale Prozessor erinnert eher an Registermaschinen. Ein wesentlicher Teil der Zeit wird damit verbracht, die Daten, die sonst auf dem Stack liegen, Registern zuzuweisen. Gerade hier kann der JIT-Compiler viel verbessern (um nicht zu sagen optimieren), und da ist es schon eine sehr hohe Kunst, ganz spezielle Befehle des realen Prozessors zu finden, die an dieser Stelle genutzt werden können. (Immerhin soll das Programm ja schnell kompiliert sein, und da muss der JIT-Compiler irgendwann fertig werden bzw. mit Optimieren aufhöhren.) Insofern kann es hier sehr auf die JIT-Compiler ankommen, ob so ein spezieller Befehl benutzt werden wird oder nicht.

Kurzum: Ob spezielle Befehle genutzt werden (können), hängt von sehr, sehr vielen Dingen ab. ;)

Ark
 

Wortraum

Bekanntes Mitglied
wenn ich nun i & 1 auswerten lasse wäre es ja unsinnig überhaupt die anderen Stellen mit Ausnahme des ersten Bits zu prüfen
Ich vermute, es wird ein Register mit einem anderen verundet, und das geschieht für alle Bits eines Wortes parallel in einem Takt.

Wie lange Java benötigt und was genau passiert, um zu prüfen, ob das Ergebnis eine 0, eine 1 oder etwas anderes ist, ist für mich so unwichtig, daß mich nicht einmal die Antwort interessiert. Das Weichenkonstrukt ist, wie bereits Jay_030 schrieb, ohnehin an dieser Stelle mißbraucht; und von einer Methode solch einem Namen erwarte ich einen Wahrheitswert, keine Ganzzahl. So, wie sie ist, kann man sie jedenfalls nicht ordentlich verwenden.
 
Zuletzt bearbeitet:

Ark

Top Contributor
Ich vermute, es wird ein Register mit einem anderen verundet, und das geschieht für alle Bits eines Wortes parallel in einem Takt.
Das sehe ich genauso.

Wie lange Java benötigt und was genau passiert, um zu prüfen, ob das Ergebnis eine 0, eine 1 oder etwas anderes ist, ist für mich so unwichtig, daß mich nicht einmal die Antwort interessiert.
An dieser Stelle bin ich definitiv anderer Meinung. Sowohl bei switches als auch bei solchen arithmetisch-logischen Ausdrücken kann man die Compiler unterstützen.

Bei switches ist es wichtig, die cases (die Werte, die der Ausdruck zum Wort [c]switch[/c] annehmen kann/muss) streng monoton steigend und möglichst geschlossen zu wählen. Wenn kein fall-through ausgenutzt wird, kann der Bytecode-Compiler die alternativen Codeteile umsortieren, um sie streng monoton steigend hinzubekommen, sonst nicht. (Ob der Compiler das macht, ist noch mal eine andere Frage.) Wenn die cases dicht genug beieinander liegen, kann eine Sprungtabelle angelegt werden, mit der dann praktisch garantiert werden kann, dass jeder Einsprung die gleiche Anzahl an Schritten benötigt; im Allgemeinen ist solcher Code auch schneller. Wenn die cases jedoch zu weit auseinanderliegen oder (trotz Umstellversuche durch den Bytecode-Compiler) nicht streng monoton steigend vorliegen, wird keine Sprungtabelle mehr eingesetzt, sondern auf ein klassisches if-else-Konstrukt gesetzt. Das kann dann dazu führen, dass weiter hinten liegende Alternativen immer später drankommen (also mit größerer Verzögerung) als frühere, und insgesamt wird die Ausführung sehr wahrscheinlich langsamer sein.

(Eventuell kann der Compiler auch bei streng monoton fallenden cases Sprungtabellen einsetzen.)

Bei arithmetisch-logischen Ausdrücken kann man zum einen die Anzahl der Operationen selbst verringern (oder sie eventuell durch schnellere austauschen), zum anderen kann man auf Ausdrücke setzen, deren Werte implizit berechnet werden. So muss bei [c](a & 1) == 1[/c] der Vergleich mit der 1 explizit durchgeführt werden, und das kostet für die Konstante 1 ein wenig Zeit und immerhin ein wertvolles Register, das man anderweitig besser nutzen könnte. Schreibt man dagegen [c](a & 1) != 0[/c], so kann der Vergleich mit 0 komplett entfallen, da das Zero-Flag bei praktisch allen Prozessoren automatisch bei der UND-Verknüpfung entsprechend gesetzt wird.

Das Weichenkonstrukt ist, wie bereits Jay_030 schrieb, ohnehin an dieser Stelle mißbraucht; und von einer Methode solch einem Namen erwarte ich einen Wahrheitswert, keine Ganzzahl. So, wie sie ist, kann man sie jedenfalls nicht ordentlich verwenden.
Dem stimme ich wieder zu.

Ark
 

Jay_030

Aktives Mitglied
Bei arithmetisch-logischen Ausdrücken kann man zum einen die Anzahl der Operationen selbst verringern (oder sie eventuell durch schnellere austauschen), zum anderen kann man auf Ausdrücke setzen, deren Werte implizit berechnet werden. So muss bei [c](a & 1) == 1[/c] der Vergleich mit der 1 explizit durchgeführt werden, und das kostet für die Konstante 1 ein wenig Zeit und immerhin ein wertvolles Register, das man anderweitig besser nutzen könnte. Schreibt man dagegen [c](a & 1) != 0[/c], so kann der Vergleich mit 0 komplett entfallen, da das Zero-Flag bei praktisch allen Prozessoren automatisch bei der UND-Verknüpfung entsprechend gesetzt wird.
Wieder etwas gelernt. Danke. :)

Das kann der Compiler ja nur schlecht selbst wegoptimieren, denn zwischenn == 1 und != 0 ist semantisch aus Sicht der Compilers ein großer Unterschied.

Wie gesagt, danke für deine Erklärungen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
pkelod Binäre Darstellung Bitwise-Operator Java Basics - Anfänger-Themen 10
U Wie genau funktioniert der ! Operator Java Basics - Anfänger-Themen 3
C ?: Operator Java Basics - Anfänger-Themen 14
L Java operator % Java Basics - Anfänger-Themen 3
KogoroMori21 Erklärung zum Ternären Operator Java Basics - Anfänger-Themen 4
B Modulo-Operator anhand eines Beispieles erklären Java Basics - Anfänger-Themen 7
C Ternärer Operator mit Strings Java Basics - Anfänger-Themen 3
L Modulus Operator Java Basics - Anfänger-Themen 3
A Zuweisungen und -- operator; Java Basics - Anfänger-Themen 2
H << Operator Java Basics - Anfänger-Themen 7
F RegEx "+" nur als Zeichen, nicht als Operator oder Sonstiges Java Basics - Anfänger-Themen 2
H Operatoren Der bedingte Operator ? : ; Java Basics - Anfänger-Themen 2
J new-Operator Java Basics - Anfänger-Themen 6
H this operator - was ist das? Java Basics - Anfänger-Themen 2
R Operatoren Bad operand types for binary operator Java Basics - Anfänger-Themen 4
O Bedingter Operator eine Frage! Java Basics - Anfänger-Themen 10
O Erste Schritte x*y*z mit Shift Operator moeglich? Java Basics - Anfänger-Themen 15
L Operatoren error: bad operand types for binary operator && Java Basics - Anfänger-Themen 8
E Methoden in new-Operator Methode in geschweifter Klammer Java Basics - Anfänger-Themen 3
I bad operand types for binary operator > Java Basics - Anfänger-Themen 5
D Conditional Operator ?: Java Basics - Anfänger-Themen 3
L Operatoren Übungsklausuraufgabe, unbekannter Operator Java Basics - Anfänger-Themen 13
H Operatoren Fehler bad operand types for binary operator Java Basics - Anfänger-Themen 7
snipesss Operator "-" is undefined Java Basics - Anfänger-Themen 1
F Operatoren If mit variabelem Operator Java Basics - Anfänger-Themen 2
J instanceof Operator Java Basics - Anfänger-Themen 3
K Operatoren The Operator * is undefined for the argument type(s) double, String Java Basics - Anfänger-Themen 4
J Operator * benutzen Java Basics - Anfänger-Themen 3
DeVolt Operatoren Frage zum new-Operator Java Basics - Anfänger-Themen 4
N Methoden Modulo Operator Java Basics - Anfänger-Themen 1
S Operatoren ! Operator Java Basics - Anfänger-Themen 4
O Operator undefined Java Basics - Anfänger-Themen 2
N this-Operator Java Basics - Anfänger-Themen 2
ubaro1 Operatoren Der Tide Operator und positive Ganzzahlen in Binär Java Basics - Anfänger-Themen 1
S Hashcode - Operator ^ Java Basics - Anfänger-Themen 11
M Shift Operator Java Basics - Anfänger-Themen 3
V XOR-Operator? Java Basics - Anfänger-Themen 5
K Zugriff einer Klasse auf eine andere Andere -> bad operand for binary operator Java Basics - Anfänger-Themen 5
J bad operand types for binary operator Java Basics - Anfänger-Themen 3
T Pixelmanipulation Sobel-Operator Java Basics - Anfänger-Themen 2
K Frage zu Class Operator Java Basics - Anfänger-Themen 2
L The operator && is undefined for the argument type(s) String, boolean Java Basics - Anfänger-Themen 8
C Operatoren | - Operator Java Basics - Anfänger-Themen 10
K .Class Operator unklar Java Basics - Anfänger-Themen 3
B Operator | Java Basics - Anfänger-Themen 11
R Compiler-Fehler Operator + nicht erlaubt? Java Basics - Anfänger-Themen 6
C Was tut der | Operator? Java Basics - Anfänger-Themen 8
K Polymorphie und instanceOf Operator Java Basics - Anfänger-Themen 6
S Objekt Erzeugung ohne new Operator Java Basics - Anfänger-Themen 6
C Logischer UND Operator funktioniert nicht richtig Java Basics - Anfänger-Themen 5
H Buch: Java lernen mit BlueJ Modulo-Operator Java Basics - Anfänger-Themen 16
K Conditional Operator Java Basics - Anfänger-Themen 16
A Was bedeutet der Operator *= ? Java Basics - Anfänger-Themen 2
A Operator in Java Java Basics - Anfänger-Themen 11
S Modulo Operator Java Basics - Anfänger-Themen 8
C Variablen Problem: variable operator might not have been initialized Java Basics - Anfänger-Themen 9
D : ? Operator -Verständnisproblem Java Basics - Anfänger-Themen 24
K OOP Wertebereich Ergebnis von % Operator Java Basics - Anfänger-Themen 8
L Frage zu Konstruktoren und dem this Operator Java Basics - Anfänger-Themen 16
R Ersatz für Modulo Operator Java Basics - Anfänger-Themen 8
J Oder-Operator Tastenkürzel Java Basics - Anfänger-Themen 7
K Cast-Operator Java Basics - Anfänger-Themen 3
D Bit-Operator & Java Basics - Anfänger-Themen 5
Q mathematische Operationen als Methode und nicht Infix-Operator Java Basics - Anfänger-Themen 14
V Cast-Operator Java Basics - Anfänger-Themen 2
G super operator und incompatible types, simple fehler Java Basics - Anfänger-Themen 8
N Operator aus Array lesen Java Basics - Anfänger-Themen 2
G Für was braucht man den This-operator Java Basics - Anfänger-Themen 3
M Binärdarstellung in Java mit Shift-Operator + bitweises und Java Basics - Anfänger-Themen 2
W Seltsamer Operator int var = 1<< 23; Java Basics - Anfänger-Themen 4
P If Abfrage, Variablenvertauschung und UND Operator Java Basics - Anfänger-Themen 4
J Modulo-Operator rechnet falsch Java Basics - Anfänger-Themen 2
B + operator Java Basics - Anfänger-Themen 4
F Generische Methode - was bringt der Wildcard Operator? Java Basics - Anfänger-Themen 7
H Konditional Operator Java Basics - Anfänger-Themen 2
NightmareVirus new operator Java Basics - Anfänger-Themen 5
M %-Operator Java Basics - Anfänger-Themen 3
G string ohne '+' operator Java Basics - Anfänger-Themen 5
S Modulo-Operator Java Basics - Anfänger-Themen 5
S Operator ! auf char nicht anwendbar, was nun? Java Basics - Anfänger-Themen 7
T sobel-operator Java Basics - Anfänger-Themen 3
W %-Operator Java Basics - Anfänger-Themen 4
S Unterschied: ++a & a++ Operator? Java Basics - Anfänger-Themen 9
ven000m Operator += Java Basics - Anfänger-Themen 4
Student Probleme mit dem new-Operator Java Basics - Anfänger-Themen 14
G Operator-Überladung Java Basics - Anfänger-Themen 6
B Operator Java Basics - Anfänger-Themen 2
Z operator ++ Java Basics - Anfänger-Themen 3
N return-Operator Java Basics - Anfänger-Themen 11
B Objekt kopieren und sämtliche Referenzen von diesem Objekt? Java Basics - Anfänger-Themen 3
S Was bedeutet ungleich (in diesem Zusammenhang)? Java Basics - Anfänger-Themen 2
jhCDtGVjcZGcfzug Was genau ist mit diesem Quellcode gemeint? Java Basics - Anfänger-Themen 5
jhCDtGVjcZGcfzug Was ist mit diesem Quellcode gemeint? Java Basics - Anfänger-Themen 3
MichelNeedhelp Brauche zu diesem Labyrinth ein Skript? Der Hamster soll im Urzeigersinn das ganze Labyrinth abgehen und wieder an seinem Ursprungsplatz sein. Java Basics - Anfänger-Themen 40
S Wie kann ich bei diesem Code erreichen, das als Ergebnis hier 15 herauskommt? Java Basics - Anfänger-Themen 23
F Methoden Bitte Helft mir meinen Fehler zu finden. Möchte in diesem Bankenprogramm durch die Konsoleneingabe auswählen welches Konto reduziert und welches erhö Java Basics - Anfänger-Themen 17
J Variablen Hilfe bei diesem Code Java Basics - Anfänger-Themen 6
L Ist an diesem Befehl irgendwas falsch? Java Basics - Anfänger-Themen 2
B Wie funktionieren diese Methoden in diesem Sortierverfahren genau? Java Basics - Anfänger-Themen 2
M problem mit diesem zeichen | Java Basics - Anfänger-Themen 10

Ähnliche Java Themen

Neue Themen


Oben