2er-Komplement

Die interne Darstellung negativer Zahlen

Positive ganze Zahlen werden intern (im PC-Speicher) ungefähr so gespeichert wie erwartet, d.h. als Binärzahlen, so wie angeschrieben. Negative Zahlen werden zum Speichern in das sog. 2er-Komplement umgewandelt. Auf dieser Seite wird das demonstriert.
BitLevel Operationen auf Bit-Ebene
Live-Demo Umwandlung ganzer Zahlen in das internbe Speicher-Format
Vorzeichen Negative Zahlen, 2er-Komplement
Verwandte Themen Interne Darstellung: Gleitkomma-Zahlen, Zeichencodes
Umwandlung Strings - (Binär)-Zahlen, Bit-Level Operatoren
Links Ausgewählte Links zum Thema '2er-Komplement'

Live-Demonstration

signed   unsigned
decbin Algorithmus
Eingabe
 
Eingabe bleibt unverändert
 0 00000000
 0 00000000
Speicherform0 00000000
Zufalls-Zahlen Zufalls-Bytes oder manuelle Eingabe in das  grün  unterlegte Feld: Dezimalzahlen 0..255 oder Bitmuster (prefix 0b ) oder Octalzahlen (führende 0 ) oder Hexadezimalzahlen (prefix # oder 0x ). Nach jeder Änderung wird die 1-Byte Speicherform berechnet. Der Zahlenwert bleibt entweder unverändert oder wird in das 2er-Komplement (Speicherform) umgerechnet.
Ind er Praxis wird der gleiche Algorithmus sinngemäß auch auf Ganzzahlen-Variablen größerer Länge (2,4,8 Byte) angewendet.

Vorzeichen und 2er-Komplement

Die meisten Programmiersprachen bieten unterschiedliche Variablen der Typen signed und unsigned, manche auch für mehrere Speichergrößen (z.B. 8 Bit, 16 Bit, 32 Bit ..).

Der Werte-Bereich für unsigned (positive ganze Zahlen) beträgt
vmin=0; vmax=2b-1
Für b=8 Bit ergibt sich z.B. ein Bereich
vmin=0; vmax=28-1=255

Für das Vorzeichen von signed Variablen wird 1 Bit benötigt. Ihr Werte-Bereich beträgt
vmin=-2b-1; vmax=2b-1-1
Für b=8 Bit ergibt sich z.B. ein Bereich
vmin=-27=-128; vmax=27-1=127
Als Vorzeichen-Bit wird das höchstwertige Bit (msb) verwendet. Die Zahlen-Bits werden allerdings nur für positive Zahlen in der normalen binären Form gespeichert.
Sie können das in der Live-Demo testen - Positive signed-Zahlen innerhalb des zulässigen Werte-Bereichs werden exakt genauso gespeichert wie unsigned-Zahlen.

Negative Zahlen werden nach einem speziellen Algorithmus (2er-Komplement) in ein Bitmuster umgewandelt. Das bringt Vorteile beim Rechnen auf Prozessor-Ebene.
Negative signed-Zahlen ergeben ein Bitmuster im gleichen Bereich wie unsigned-Zahlen der oberen Werte-Hälfte

Das gleiche Bitmuster kann daher unterschiedlich interpretiert werden, je nach der vereinbarten Variablen-Type !
Sie können das in der Live-Demo testen, wenn sie zwischen signed und unsigned umschalten.

Umwandlung Negative Zahl → 2er-Komplement

+ Positive Zahlen (innerhalb des Werte-Bereichs) bleiben unverändert.
+ Das Vorzeichen negativer Zahlen wird umgekehrt.
+ Alle Bits werden umgekehrt
+ 1 wird addiert

Beispiel-Vorgaben (Zahl, Speicher-Breite in Bit)
n=-4; b=8;
BitLevel-Algorithmus (ohne Gewähr ! - Javascript bis b<32 )
k=n;
if(k<0) {
mask=(2^b)-1;
k=((~(-k)) & mask)+1;
}
ergibt
k=252

Numerischer Algorithmus (ohne Gewähr ! - Javascript bis b<56 )
k=n;
if(k<0) {
mask=(2^b);
k=mask+n;
}

Umwandlung 2er-Komplement → Negative Zahl

+ Nur Zahlenwerte der oberen Hälfte des Werte-Bereichs werden umgewandelt.
+ 1 wird subtrahiert
+ Alle Bits werden invertiert
+ Das Vorzeichen wird umgekehrt

Beispiel-Vorgaben (Speicherwert, Bit)
k=252; b=8;
BitLevel-Algorithmus (ohne Gewähr !)
n=k;
mask=(2^b)-1;
halb=mask >> 1;
if(n>halb) {n=-((~(n-1)) & mask);}
ergibt
n=-4

Numerischer Algorithmus (ohne Gewähr !)
n=k;
mask=(2^b);
if(n>mask/2) {
n=k-mask;
}
Die Bit-Umkehrung mit dem BitLevel NOT-Operator birgt eine besondere Falle:
Die binäre Darstellung positiver Zahlen enthält theoretisch unendlich viele führende 0-Bits. Praktisch ist die Anzahl führender 0-Bits durch die vereinbarte Speicher-Größe (z.B. 8,16,32 Bit) begrenzt. Moderne Programmiersprachen ohne ausdrückliche Typ-Vereinbarung entscheiden jedoch selbst die benötigte Speicher-Größe !
Die Bit-Umkehrung verwandelt jedes 0-Bit in ein 1-Bit. Bei dynamischer Speichergröße ergibt das eine unbekannte Anzahl führender 1-Bits und damit eine gefährliche Fehlerquelle !
Abhilfe:
Nach jeder verdächtigen Operation (z.B. nach Bit-Inversion) wird die Anzahl der weiter verarbeiteten Bits justiert.
Im Beispiel oben wird das durch Anwendung des BitLevel AND-Operators mit der Zahl 255 (für 1 Byte Speicherbreite) bewirkt.
Für andere Speicher-Formate (b Bits) verwenden sie jeweils die Zahl 2b-1