Advent/2023/07
Adventskalender 2023 - 07.12. <<, >> und >>>
Die Operatoren <<
, >>
und >>>
dienen der bitweisen Verschiebung von ganzahligen Werten. Links vom Operator steht der zu verschiebende Wert, und rechts davon die Anzahl von Bits, um die verschoben werden soll.
Unser Artikel über Rechnerarithmetik erklärt die Grundlagen, wie Zahlen im Computer dargestellt werden. JavaScript speichert Zahlen prinzipiell als IEEE 754 Fließkommazahlen, aber die Verschiebungsoperatoren arbeiten mit 32-bittigen Integerwerten. Das heißt: Wenn der Computer den Ausdruck a << 3
auswerten soll, muss er zunächst einmal den Inhalt von a
in eine 32-bittige Integerzahl umwandeln. Angenommen, in a
steht der Wert "1234.5"
. Das ist eine Zeichenkette, die sich in eine Fließkommazahl umwandeln lässt. Danach werden die nachkommastellen abgeschnitten, und das Ergebnis ist 1234
oder 10011010010
als Binärzahl. Der Übersicht halber soll die Verschiebung für ein 16-bittige Darstellung gezeigt werden. Unsere 11-bittige Beispielzahl wird mit Nullbits auf 16 Stellen aufgefüllt. Damit sie erkennbar bleibt, haben wir sie blau eingefärbt.
16-bit Register | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1234 als 16-bit Binärzahl | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | |||
<< 3 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | ? | ? | ? |
Ergebnis | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
Die rot markierten Bitpositionen gehen bei der Verschiebung verloren. Dafür werden von links neue, leere Bits hineingeschoben, die den Wert 0 haben. Das Ergebnis beträgt 00100110100100002
oder 9872
im Zehnersystem. Weil wir die Binärziffern um drei Stellenpositionen des Zweiersystems hochgeschoben haben, entspricht das Ergebnis einer Multiplikation mit 8.
Bei der Verschiebung nach rechts kennt JavaScript zwei Varianten, die sich in der Art unterscheiden, wie die Fragezeichen aufgefüllt werden. Der >>
-Operator füllt mit Nullbits auf. Solange man reine Bitmuster oder positive Zahlenwerte schiebt, ist das problemlos. Schiebt man aber negative Zahlen, führt das zu einer Werteverfälschung, weil das höchste Bit hierbei gesetzt bleiben muss. Darum gibt es auch den >>>
-Operator, der den Wert des höchsten Bits in die freiwerdenden Bitstellen überträgt.
16-bit Register | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
-1234 als 16-bit Binärzahl | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | könnte aber auch 64302 bedeuten! | |||
>> 3 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 8037 |
>>> 3 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | -155 oder 65381 |
Die rot dargestellten Bits fallen nach der Verschiebung wieder weg. Ob für den gewünschten Zweck der >>
oder >>>
richtig ist, kann man nicht sagen. Es hängt davon ab, welche Bedeutung das geschobene Bitmuster für die Aufgabenstellung hat. 64302 / 8 ergibt 8037, wenn man mit vorzeichenlosen 16-bit Werten rechnet, ist das das richtige Ergebnis. Mit Vorzeichen ergibt -1234 / 8 den Wert -155.
In seltenen Fällen muss man in JavaScript tatsächlich auf Bitebene arbeiten. Wenn die Aufgabenstellung lautet, in die Bits 12-15 eines Bitmusters einen Wert einzutragen, dann ist es nützlich, diesen Wert mit dem <<
Operator um 12 Bits nach links zu schieben. Außer <<
und >>
benötigt man dann auch noch die Operatoren &&
, ||
, ^
und ~
, um wirklich jedes Bit einzeln beim Vornamen anreden zu können.
Aber ansonsten ist die häufigste Anwendung in JavaScript, mittels einer Verschiebung um 0 Stellen einen Wert von seinen Nachkommastellen zu befreien.