Ratgeber · 7 Min Lesezeit

Zweierkomplement: negative Zahlen im Binärsystem

Warum Computer negative Ganzzahlen nicht mit einem Vorzeichen-Bit darstellen, sondern als Zweierkomplement. Mit Schritt-für-Schritt-Anleitung und Praxisbeispielen.

Im Dezimalsystem ist Negativität einfach: vor der Zahl steht ein Minus, fertig. Im Binärsystem wäre der naheliegende Ansatz, ein Bit als Vorzeichen zu reservieren. Genau so haben es frühe Computer auch gemacht, mit dem sogenannten Vorzeichen-Betrag-Verfahren. Es hat sich aber nicht durchgesetzt. Stattdessen nutzen heute praktisch alle Prozessoren das Zweierkomplement. Warum?

Das Problem mit dem Vorzeichen-Bit

Stellen wir uns 8-Bit-Zahlen mit Vorzeichen-Betrag-Darstellung vor. Das höchste Bit codiert das Vorzeichen (0 für plus, 1 für minus), die restlichen sieben Bit den Betrag. 00000101 wäre +5, 10000101 wäre -5. Klingt logisch.

Zwei Probleme tauchen sofort auf:

Es gibt zwei Nullen. 00000000 ist +0, 10000000 ist -0. Mathematisch derselbe Wert, im Bitmuster verschieden. Jeder Vergleich auf null muss beide Fälle prüfen.

Addition wird kompliziert. Will man +5 und -3 addieren, muss die Hardware zuerst die Vorzeichen prüfen, dann entscheiden, ob addiert oder subtrahiert wird, dann das Ergebnis-Vorzeichen bestimmen. Aus einer einzigen Operation werden mehrere Sonderfälle.

Das Zweierkomplement löst beide Probleme elegant.

Wie Zweierkomplement funktioniert

Die Regel ist erstaunlich einfach: um die negative Form einer Zahl zu bekommen, invertiert man alle Bits und addiert 1. Das war’s.

Beispiel mit 8 Bit, gesucht ist die Darstellung von -5:

+5            00000101
Bits invertieren  11111010
+1                00000001
                  --------
-5            11111011

Probe: Addiert man +5 und -5, sollte 0 herauskommen:

  00000101
+ 11111011
  --------
 100000000

Das neunte Bit kippt heraus (es passt nicht in unsere 8 Bit), übrig bleibt 00000000. Genau die Null, die wir erwartet haben. Und es gibt nur eine, denn 10000000 ist im Zweierkomplement nicht mehr -0, sondern -128.

Der Wertebereich

In 8 Bit ohne Vorzeichen geht der Bereich von 0 bis 255. Im Zweierkomplement reicht er von -128 bis +127. Das höchste Bit ist immer noch das Vorzeichen, aber jetzt mit einer anderen Bedeutung: ist es 1, steht die Zahl für ihren Wert minus 2ⁿ, wobei n die Bitbreite ist.

BitbreiteMinimumMaximum
8 Bit-128+127
16 Bit-32.768+32.767
32 Bit-2.147.483.648+2.147.483.647
64 Bit-9.223.372.036.854.775.808+9.223.372.036.854.775.807

Auffällig: der negative Bereich reicht immer eine Einheit weiter als der positive. Der Grund ist die einzelne Null, die im positiven Bereich „verbraucht” wird.

Warum Addition und Subtraktion plötzlich gleich sind

Der zweite Vorteil ist der entscheidende: Im Zweierkomplement funktioniert die normale Binäraddition automatisch korrekt, egal ob die Operanden positiv oder negativ sind. Die Hardware muss nichts unterscheiden, sie addiert einfach Bit für Bit und ignoriert eventuelle Überläufe in der höchsten Stelle.

Das heißt auch: Subtraktion ist Addition des Zweierkomplements. Will der Prozessor 7 - 3 rechnen, bildet er das Zweierkomplement von 3 (also -3) und addiert es auf 7. Damit braucht es keine eigene Subtraktions-Hardware, dieselben Volladdierer-Schaltungen reichen für beide Operationen.

Das ist der Hauptgrund, warum sich Zweierkomplement durchgesetzt hat: es spart Chip-Fläche und macht die ALU einfacher und schneller.

Sign Extension

Wenn eine 8-Bit-Zahl auf 16 Bit erweitert wird, muss das Vorzeichen erhalten bleiben. Bei positiven Zahlen werden die neuen Bits mit 0 aufgefüllt, bei negativen mit 1. Dieser Vorgang heißt Sign Extension oder Vorzeichenerweiterung.

+5 in 8 Bit:   00000101
+5 in 16 Bit:  00000000 00000101  (links mit 0 aufgefüllt)

-5 in 8 Bit:   11111011
-5 in 16 Bit:  11111111 11111011  (links mit 1 aufgefüllt)

Probe: wäre -5 fälschlich mit 0 aufgefüllt worden (00000000 11111011), würde es im 16-Bit-Bereich als +251 interpretiert. Sign Extension verhindert genau diesen Fehler.

In C unterscheiden sich int8_t und uint8_t deshalb beim Zuweisen an größere Typen, was eine häufige Fehlerquelle bei niedriger Programmierung ist.

Überlauf erkennen

Was passiert, wenn 100 + 50 in 8 Bit (Zweierkomplement) gerechnet wird? Mathematisch wären das 150, aber 150 passt nicht mehr in den 8-Bit-Bereich (Maximum ist 127). Das Ergebnis-Bitmuster ist 10010110, was als vorzeichenbehaftete Zahl gelesen -106 bedeutet.

Solche Überläufe sind echte Programmierfehler-Quellen. Prozessoren setzen ein Overflow-Flag, wenn so etwas passiert, aber höhere Programmiersprachen melden das nicht automatisch. In C ist signed-Integer-Überlauf sogar undefiniertes Verhalten, der Compiler darf alles annehmen, und tatsächlich entstehen so reale Sicherheitslücken.

Anwendung in der Praxis

Wer in Java, C, C#, Rust, Go oder einer anderen verbreiteten Sprache mit Integer-Typen arbeitet, nutzt im Hintergrund Zweierkomplement. Die negative Zahl -1 in Java ist als int das Bitmuster 11111111 11111111 11111111 11111111. Wer das versteht, kann etwa mit dem Trick x & (x - 1) das niedrigste gesetzte Bit löschen, ohne über Vorzeichen nachdenken zu müssen.

Auch bitweise Operatoren arbeiten direkt auf den Bitmustern, unabhängig von der Vorzeichen-Interpretation. Erst beim Ausdrucken oder Vergleichen mit anderen Zahlen kommt das Vorzeichen wieder ins Spiel.

Verwandte Themen

Zur weiteren Vertiefung: Bitweise Operatoren, Endianness, und für die Anwendung beim Rechnen unser Artikel Dezimal zu Binär umrechnen.

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige