Rechnen
Zweierkomplement: wie Computer negative Zahlen speichern
Ein Byte hat kein Minuszeichen. Das Zweierkomplement ist der Trick, mit dem acht ganz normale Bits für −128 bis 127 stehen können. Und er funktioniert so gut, dass derselbe Addierer positive und negative Zahlen verarbeitet, ohne den Unterschied überhaupt zu kennen.
Die Kurzfassung
In einer 8-Bit-Zahl im Zweierkomplement ist das linke Bit −128 wert statt +128. Alle anderen Bits behalten ihre gewohnte positive Wertigkeit (64, 32, 16, 8, 4, 2, 1). Das ist die ganze Definition. Alles andere folgt daraus.
Eine Zahl im Zweierkomplement lesen
Zähl die Wertigkeiten aller Bits zusammen, die 1 sind – und denk dran, dass das oberste negativ ist:
00000101= 4 + 1 = 511111111= −128 + 127 = −110000000= −128, das negativste Byte01111111= 127, das größte positive Byte
Ist das oberste Bit 0, ist die Zahl null oder positiv und liest sich genau wie eine normale vorzeichenlose Zahl. Ist es 1, ist die Zahl negativ. Deshalb heißt das oberste Bit oft Vorzeichenbit – aber anders als ein echtes Minuszeichen hat es eine Wertigkeit und rechnet ganz normal mit.
Das Kilometerzähler-Bild
Man kann es auch so sehen: Ein 8-Bit-Register ist ein Zähler, der nach 255 wieder bei 0 anfängt, wie ein Kilometerzähler, der von 99999 auf 00000 springt. Zählst du von 0 rückwärts, landest du bei 255, dann 254, dann 253. Das Zweierkomplement vereinbart einfach, diese Werte −1, −2 und −3 zu nennen. Eine negative Zahl −x wird als 256 − x gespeichert.
Genau deshalb klappt es mit ganz normaler Addition. In einem 8-Bit-Register ändert das Addieren von 256 nichts, weil die zusätzliche 1 oben herausfällt. 256 − x zu addieren ist also dasselbe, wie x abzuziehen. Probier es aus: 7 + (−5) ist 00000111 + 11111011 = 1 00000010. Lass das neunte Bit weg, und das Ergebnis ist 2.
Wertebereich
| Bits | Vorzeichenlos | Zweierkomplement |
|---|---|---|
| 4 | 0 … 15 | −8 … 7 |
| 8 | 0 … 255 | −128 … 127 |
| 16 | 0 … 65.535 | −32.768 … 32.767 |
| 32 | 0 … 4.294.967.295 | −2.147.483.648 … 2.147.483.647 |
Es gibt eine negative Zahl mehr als positive, weil die Null eines der „nicht negativen“ Bitmuster belegt. Kuriose Folge: Negierst du −128 in einem Byte, kommt wieder −128 heraus, denn +128 passt nicht hinein.
Warum nicht einfach ein Vorzeichenbit?
Die naheliegende Idee, der Betrag mit Vorzeichen, nutzt ein Bit für das Vorzeichen und den Rest für den Betrag, so wie wir auf Papier schreiben. Manche frühen Computer machten das so, andere nutzten das Einerkomplement, bei dem man zum Negieren jedes Bit umdreht. Beide haben zwei Nullen (+0 und −0), und beide brauchen zusätzliche Logik, damit die Addition einer negativen Zahl das richtige Ergebnis liefert. Das Zweierkomplement hat genau eine Null, und der ganz normale Binäraddierer rechnet schon richtig. Diese Ersparnis an Hardware ist der Grund, warum praktisch jeder Prozessor seit den 1970ern damit arbeitet. Die große Ausnahme sind Gleitkommazahlen: Die haben ein separates Vorzeichenbit.
Zweierkomplement von Hand berechnen
Um eine negative Zahl −x mit n Bits darzustellen, berechnest du 2n − x und schreibst das binär. Für −5 mit 8 Bits: 256 − 5 = 251 = 11111011. In die andere Richtung liest du die Zahl so, dass das oberste Bit −2n−1 wert ist, wie oben. Beide Wege folgen direkt aus der Definition und funktionieren immer.
Spoiler zum Negations-Rätsel im Spiel: die Abkürzung
Es gibt eine bekannte Abkürzung zum Negieren ganz ohne Subtraktion: alle Bits invertieren, dann 1 addieren. Für 5: 00000101 → 11111010 → 11111011, also −5. Das klappt, weil eine Zahl plus ihr bitweise umgedrehter Zwilling immer 11111111 ergibt, also −1. Im Spiel baust du eine Negationsschaltung – überspring diesen Kasten, wenn du selbst auf die Idee kommen willst.
Überlauf
Rechnest du 100 + 100 in einem vorzeichenbehafteten Byte, kommt 11001000 heraus, und das bedeutet −56. Das richtige Ergebnis 200 liegt außerhalb des Bereichs, es ist übergelaufen. Das verräterische Zeichen: Zwei Zahlen mit gleichem Vorzeichen ergeben ein Ergebnis mit dem anderen Vorzeichen. CPUs halten das im Overflow-Flag fest, getrennt vom Carry-Flag für vorzeichenlose Zahlen. Der Addierer liefert in beiden Fällen dieselben Bits; ob sie als vorzeichenbehaftet oder vorzeichenlos gelten, entscheidet das Programm. Deshalb haben viele Befehlssätze zwei Sätze von Vergleichs- und Sprungbefehlen.
Vorzeichenerweiterung
Um eine vorzeichenbehaftete Zahl breiter zu machen, etwa von 8 auf 16 Bit, kopierst du das Vorzeichenbit in alle neuen Bits. −5 als Byte ist 11111011, als 16-Bit-Wort 11111111 11111011. Eine positive Zahl bekommt Nullen, wie zu erwarten. Befehlssätze, die Bytes in breitere Register laden, bieten genau deshalb meist eine „signed“- und eine „unsigned“-Variante des Ladebefehls.