Operatoren Logischer Rightshift von negativen Zahlen auf Bit-Ebene

DeBukkIt

Mitglied
Hallo!
Ich habe versucht, die Operation -3 >>> 5 per Stift und Papier auf Bit-Ebene (binäre Darstellung) nachzuvollziehen. Wichtig: Operanden und Ergebnis jeweils vom Typ byte. Vorgehensweise:
1111 1101 (-3 per Zweier-Komplement)
>>> 5
0000 0111 (7)

Java allerdings spuckt nicht 7, sondern immer -1 als Ergebnis aus. Warum?
Java:
System.out.println((byte) (((byte) -3) >>> ((byte) 5))); // -1

Meine erste Idee: Das Zweier-Komplement der negativen Zahl wird zunächst gebildet, dann geshiftet und anschließend wird das Zweier-Komplement wieder gebildet (naja, eigentlich müsste da aber noch eine 1 addiert werden, dann käme aber nicht mehr das Ergebnis -1 heraus, das auch Java ausspuckt, also hier der Zustand nach dem Invertieren, aber vor dem Addieren der 1, die für das Zweier-Komplement nötig wäre):
1111 1101 (-3)
Zweier-Komplement
0000 0011 (3)
>>> 5
0000 0000 (0)
Zweier-Komplement ohne +1!!!
1111 1111 (-1)

Kann mir jemand verraten, wie genau Java beim Verschieben von negativen byte-Werten (Zweier-Komplement) vorgeht? Bin ich mit meinen Vorgehensweisen auf dem richtigen Dampfer? Warum ist -1 und nicht 7 das Ergebnis?

Vielen Dank im Voraus,
DeBukkIt
 

Meniskusschaden

Top Contributor
Beim Operator >> wird einfach links mit dem MSB aufgefüllt (also dem Vorzeichenbit) und beim Operator >>>mit 0. Da wird also nichts mehr im Zweierkomplement hin und her gerechnet.

Wenn der Shift-Operator auf den Datentyp byte angewandt wird, wird vorher allerdings implizit ein cast nach int vorgenommen. Dadurch ergibt sich folgendes:
Code:
1111 1101 (-3 als byte)
1111 1111 1111 1111 1111 1111 1111 1101 (-3 nach implizitem cast aus shift-Operation >>>5)
0000 0111 1111 1111 1111 1111 1111 1111 (134217727 nach eigentlicher shift-Operation >>>5)
1111 1111 (-1 nach explizitem cast in byte)
 

Thallius

Top Contributor
Beim Operator >> wird einfach links mit dem MSB aufgefüllt (also dem Vorzeichenbit) und beim Operator >>>mit 0. Da wird also nichts mehr im Zweierkomplement hin und her gerechnet.

Wenn der Shift-Operator auf den Datentyp byte angewandt wird, wird vorher allerdings implizit ein cast nach int vorgenommen. Dadurch ergibt sich folgendes:
Code:
1111 1101 (-3 als byte)
1111 1111 1111 1111 1111 1111 1111 1101 (-3 nach implizitem cast aus shift-Operation >>>5)
0000 0111 1111 1111 1111 1111 1111 1111 (134217727 nach eigentlicher shift-Operation >>>5)
1111 1111 (-1 nach explizitem cast in byte)

Für solche "eigenlogik" gehört der Programmierer der Shift Funktion geteert und gefedert...
 

DeBukkIt

Mitglied
Vielen Dank für die Hilfe! Damit kann ich die Operation endlich nachvollziehen. Aber, genau wie Thallius es sagte: Wer kommt auf solch einen Schwachsinn?

Letzte Frage: Gibt es eine Java-Dokumentation/-Spezifikation, mit der sich genau dieser Vorgang (cast nach Integer und zurück nach Byte) belegen lässt?
 

Meniskusschaden

Top Contributor
... und zurück nach Byte
Hier wird nicht zu einem Byte-Objekt zurück gecastet, sondern zum primitiven Typen byte (Groß-/Kleinschreibung beachten). Das zurück casten geschieht aber nicht automatisch, sondern du hast es explizit aufgerufen. Beispiel:
Java:
System.out.println((byte)(-3 >>> 5));   // -1
System.out.println(       -3 >>> 5);    // 134217727

Gibt es eine Java-Dokumentation/-Spezifikation, mit der sich genau dieser Vorgang (cast nach Integer und zurück nach Byte) belegen lässt?
Wenn ich die Spezifikation richtig verstehe (was keinesfalls sicher ist), ergibt sich das hieraus und der dort enthaltenen Verlinkung zu diesem Abschnitt.
 
Zuletzt bearbeitet:

mariane

Mitglied
Die Frage ist, was du als Ergebnis erwartest.
Wenn ...

System.out.println((byte) (-3 >>> 5));
... 7 ergeben soll, etwa weil es dir nicht um -3 geht sondern um die gesetzen Bits, dann muß du vorher auf 8-bit mit 0xFF maskieren, also ...

System.out.println((byte) ((0xFF & -3) >>> 5));
... verwenden.
 

Ähnliche Java Themen

Neue Themen


Oben