Start · Sprachen · JavaScript · Referenz · Unsigned Right Shift Zuweisung (>>>=)

Unsigned Right Shift Zuweisung (>>>=)

Operator

Verschiebt die Bits von <code>x</code> ohne Vorzeichen um <code>y</code> Stellen nach rechts und weist das Ergebnis <code>x</code> zu. Das Ergebnis ist immer eine nicht-negative 32-Bit-Ganzzahl.

seit JavaScript ES1 (Baseline: alle Browser) Kategorie: syntax

Signatur

x >>>= y

Beschreibung

Der Zuweisungsoperator >>>= ist die Kurzform von x = x >>> y. Der Unterschied: Der Ausdruck x wird nur einmal ausgewertet. Das ist wichtig, wenn links zum Beispiel obj[getKey()] steht. Der linke Operand wird in eine vorzeichenlose 32-Bit-Ganzzahl (Uint32) umgewandelt. Dann werden seine Bits um y Stellen nach rechts geschoben, und von links werden immer Nullen nachgefüllt.

Anders als beim vorzeichenbehafteten Rechtsshift >>= bleibt das Vorzeichenbit hier nicht erhalten. Deshalb ist das Ergebnis immer eine Zahl zwischen 0 und 4294967295 (232−1). Negative Zahlen werden also zu großen positiven Werten. Ein oft genutzter Trick ist x >>>= 0: Damit wandelt man einen Wert in eine vorzeichenlose 32-Bit-Zahl um. Das braucht man häufig bei Hash-Funktionen, Prüfsummen (CRC32) oder Farbwerten.

Typische Einsatzgebiete:

  • Bits einzeln abarbeiten, zum Beispiel gesetzte Bits zählen oder ein Bitfeld durchlaufen
  • Bytes aus einem 32-Bit-Wert herauslösen (RGBA-Farben, Netzwerkprotokolle, Binärformate)
  • Zwischenergebnisse von Hash- oder Zufallszahlen-Algorithmen in den vorzeichenlosen Wertebereich bringen

Parameter

Name Typ Default Beschreibung
$x Pflicht Variable | Eigenschaft (number) Ziel der Zuweisung. Das muss eine zuweisbare Referenz sein, also eine let/var-Variable, eine Objekteigenschaft oder ein Array-Element. Der Wert wird mit ToUint32 in eine vorzeichenlose 32-Bit-Ganzzahl umgewandelt.
$y Pflicht number Anzahl der Bitstellen, um die verschoben wird. Es zählen nur die unteren 5 Bits (y & 31), also Werte von 0 bis 31. 32 wirkt deshalb wie 0.

Rückgabewert

Typ
number
Beschreibung
Der neue Wert von x, eine Ganzzahl zwischen 0 und 4294967295. Der gesamte Zuweisungsausdruck liefert ebenfalls diesen Wert.

Beispiele

Grundlagen: positive und negative Werte

let a = 5;      // 0b101
a >>>= 2;
console.log(a); // 0b1

let b = -5;     // als Uint32: 4294967291
b >>>= 2;
console.log(b);

// Vergleich mit dem vorzeichenbehafteten Shift
let c = -5;
c >>= 2;
console.log(c);
1 1073741822 -2

Gesetzte Bits zählen (funktioniert auch bei negativen Zahlen)

const popcount = (n) => {
  let count = 0;
  while (n) {
    count += n & 1;
    n >>>= 1; // mit >>= würde die Schleife bei negativen Zahlen nie enden
  }
  return count;
};

console.log(popcount(0b1011)); // 3
console.log(popcount(-1));     // alle 32 Bits gesetzt
3 32

RGBA-Farbwert in einzelne Bytes zerlegen

let color = 0xFF8800CC; // R=255, G=136, B=0, A=204
const bytes = [];

for (let i = 0; i < 4; i++) {
  bytes.unshift(color & 0xFF);
  color >>>= 8;
}

console.log(bytes);
[255, 136, 0, 204]

FNV-1a-Hash als vorzeichenlose Zahl

const fnv1a = (str) => {
  let hash = 0x811c9dc5;
  for (const ch of str) {
    hash ^= ch.codePointAt(0);
    hash = Math.imul(hash, 0x01000193);
  }
  hash >>>= 0; // in den Bereich 0 … 2^32−1 bringen
  return hash.toString(16).padStart(8, '0');
};

console.log(fnv1a('hello'));
4f9f2cab

Fallstricke: Shift-Anzahl, BigInt und const

let x = 256;
x >>>= 32;      // 32 & 31 === 0, also keine Verschiebung
console.log(x);
x >>>= 33;      // entspricht >>>= 1
console.log(x);

let big = 16n;
try {
  big >>>= 1n;
} catch (e) {
  console.log(e.constructor.name);
}

const k = 8;
try {
  k >>>= 1;
} catch (e) {
  console.log(e.constructor.name);
}
256 128 TypeError TypeError

// Wichtig · Fallstricke

  • Kein BigInt: Für BigInt gibt es keinen vorzeichenlosen Rechtsshift, weil BigInts keine feste Bitbreite haben. >>>= mit BigInt-Operanden wirft einen TypeError. Nimm stattdessen >>= oder BigInt.asUintN().
  • Shift-Anzahl wird maskiert: Es zählt nur y & 31. Deshalb setzt x >>>= 32 den Wert nicht auf 0.
  • 32-Bit-Kürzung: Nachkommastellen und Bits oberhalb von Bit 31 gehen verloren. 2**32 + 5 wird zu 5, 3.9 wird zu 3. NaN, Infinity und nicht-numerische Strings ergeben 0.
  • Negative Werte: Schon >>>= 0 macht aus -1 den Wert 4294967295. Das ist bei vorzeichenbehafteten Daten oft unerwünscht.
  • Mit const-Bindungen gibt es einen TypeError, weil eine Zuweisung stattfindet. Für die Arbeit mit großen Binärdaten sind oft Uint32Array oder DataView besser geeignet.