Wie werden Ganzzahlen in Java intern auf Bitebene dargestellt?

83

Ich versuche zu verstehen, wie Java Integer intern speichert. Ich weiß, dass alle primitiven Java-Ganzzahlen signiert sind (außer kurz?). Das bedeutet, dass in einem Byte ein Bit weniger für die Nummer verfügbar ist.

Meine Frage ist, werden alle ganzen Zahlen (positiv und negativ) als Zweierkomplement gespeichert oder sind nur negative Zahlen im Zweierkomplement?

Ich sehe, dass die Spezifikationen sagt x bit two's complement number. Aber ich werde oft verwirrt.

Zum Beispiel:

  int x = 15; // Stored as binary as is?  00000000 00000000 00000000 00001111?
  int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010

Bearbeiten

Deutlich sein, x = 15

   In binary as is: `00000000 00000000 00000000 00001111'
  Two's complement: `11111111 11111111 11111111 11110001`

Wenn Ihre Antwort lautet, dass allZahlen als Zweierkomplement gespeichert sind, dann:

  int x = 15; // 11111111 11111111 11111111 11110001
  int y = -22 // 11111111 11111111 11111111 11101010

Die Verwirrung hier ist wieder das Zeichen sagt, beide sind negative Zahlen. Kann ich es falsch verstehen / missverstehen?

Bearbeiten Ich bin mir nicht sicher, ob meine Frage verwirrend ist. Gezwungen, die Frage zu isolieren:

Meine Frage genau: Werden positive Zahlen gespeichert, binary as iswährend negative Zahlen gespeichert werden two's complement?

Einige sagten, dass alle im Zweierkomplement gespeichert sind und eine Antwort besagt, dass nur negative Zahlen als Zweierkomplement gespeichert sind.

Kevin Rave
quelle
Das Zweierkomplement bedeutet notwendigerweise, dass positive Zahlen durch die tatsächlichen Bitwerte dieser Zahl dargestellt werden ... zumindest so, wie ich es verstehe. BEARBEITEN: Außerdem bedeutet das Kompliment von zwei ein Bit weniger in der Gesamtzahl der Bytes im Grundelement, nicht ein Bit weniger pro Byte.
LJ2
Ihre Annahme ist richtig: Positive und negative Zahlen sind das Zweierkomplement, und Ihre xund ysind richtig.
Lordo
Eine Randnotiz: Es ist so etwas wie eine WTF, dass Java, eine Sprache des Internet-Zeitalters, keinen Datentyp hat, der z. TCP / IP-Portnummer (16-Bit-Wert ohne Vorzeichen) genau, was manchmal zu wirklich hässlichem Code führt.
Hyde
Überprüfen Sie den Wiki-Artikel en.wikipedia.org/wiki/… Die 2-Komplement-Nummer, die Sie für 15 angegeben haben, ist falsch
Dungeon Hunter
@hyde 'Wirklich hässlicher Code' wie?
Marquis von Lorne

Antworten:

102

Beginnen wir mit der Zusammenfassung der primitiven Java-Datentypen:

Byte : Der Byte-Datentyp ist eine 8-Bit -Zweierkomplement-Ganzzahl mit Vorzeichen .

Kurz : Der kurze Datentyp ist eine 16-Bit -Zweierkomplement-Ganzzahl mit Vorzeichen .

int: Der Int-Datentyp ist eine 32-Bit -Zweierkomplement-Ganzzahl mit Vorzeichen .

long: Der Long-Datentyp ist eine 64-Bit-Ganzzahl mit zwei Vorzeichen .

float: Der Float-Datentyp ist ein 32-Bit-IEEE 754-Gleitkomma mit einfacher Genauigkeit .

double : double data type ist ein 64-Bit-IEEE 754-Gleitkomma mit doppelter Genauigkeit .

Boolescher Wert: Der boolesche Datentyp repräsentiert ein Informationsbit .

Der Datentyp char: char ist ein einzelnes 16-Bit-Unicode-Zeichen .

Quelle

Zwei ergänzen

"Das gute Beispiel aus dem Wiki ist, dass die Beziehung zum Zweierkomplement durch die Feststellung realisiert wird, dass 256 = 255 + 1 ist und (255 - x) das Einerkomplement von x ist

0000 0111 = 7 Zweierkomplement ist 1111 1001 = -7

Die Art und Weise, wie es funktioniert, ist, dass das MSB (das höchstwertige Bit) einen negativen Wert erhält, also im obigen Fall

-7 = 1001 = -8 + 0+ 0+ 1

Positive ganze Zahlen werden im Allgemeinen als einfache Binärzahlen gespeichert (1 ist 1, 10 ist 2, 11 ist 3 usw.).

Negative ganze Zahlen werden als Zweierkomplement ihres Absolutwerts gespeichert. Das Zweierkomplement einer positiven Zahl ist bei Verwendung dieser Notation eine negative Zahl.

Quelle

Da ich für diese Antwort einige Punkte erhalten habe, habe ich beschlossen, weitere Informationen hinzuzufügen.

Eine detailliertere Antwort:

Unter anderem gibt es vier Hauptansätze, um positive und negative Zahlen in Binärzahlen darzustellen, nämlich:

  1. Signierte Größe
  2. Komplement
  3. Zweierkomplement
  4. Vorspannen

1. Signierte Größe

Verwendet das höchstwertige Bit zur Darstellung des Vorzeichens, die verbleibenden Bits zur Darstellung des Absolutwerts. Wobei 0 eine positive Zahl und 1 eine negative Zahl darstellt , Beispiel:

1011 = -3
0011 = +3

Diese Darstellung ist einfacher. Sie können Binärzahlen jedoch nicht auf die gleiche Weise wie Dezimalzahlen hinzufügen, was die Implementierung auf Hardwareebene erschwert. Darüber hinaus verwendet dieser Ansatz zwei binäre Muster, um die Werte 0, 100 ... 0 und 0 ... 0 darzustellen.

2. Die Ergänzung

In dieser Darstellung invertieren wir alle Bits einer bestimmten Zahl, um ihre Komplementarität herauszufinden. Beispielsweise:

010 = 2, so -2 = 101 (inverting all bits).

Das Problem dieser Darstellung besteht darin, dass noch zwei Bitmuster existieren, um die 0 (00..0 und 11..1) darzustellen.

3. Zweierkomplement

Um das Negativ einer Zahl zu finden, invertieren wir in dieser Darstellung alle Bits und fügen dann ein Bit hinzu. Das Hinzufügen eines Bits löst das Problem, dass zwei Bitmuster 0 darstellen. In dieser Darstellung haben wir nur eines (00 ... 0).

Zum Beispiel wollen wir die binäre negative Darstellung von 4 (dezimal) mit 4 Bits finden. Zuerst konvertieren wir 4 in binär:

4 = 0100

dann invertieren wir alle Bits

0100 -> 1011

Zum Schluss fügen wir noch ein bisschen hinzu

1011 + 1 = 1100.

1100 entspricht also -4 in Dezimalzahl, wenn wir eine binäre Zwei-Komplement-Darstellung mit 4 Bits verwenden.

Ein schnellerer Weg, das Komplementäre zu finden, besteht darin, das erste Bit als Wert 1 zu fixieren und die verbleibenden Bits zu invertieren. Im obigen Beispiel wäre es ungefähr so:

0100 -> 1100
^^ 
||-(fixing this value)
|--(inverting this one)

Die Zweierkomplementdarstellung enthält nicht nur eine Darstellung für 0, sondern fügt auch zwei Binärwerte auf dieselbe Weise hinzu wie in dezimalen, geraden Zahlen mit unterschiedlichen Vorzeichen. Es ist jedoch notwendig, nach Überlauffällen zu suchen.

4. Bias

Diese Darstellung wird verwendet, um den Exponenten in der IEEE 754-Norm für Gleitkommazahlen darzustellen. Es hat den Vorteil, dass der Binärwert mit allen Bits auf Null den kleinsten Wert darstellt. Und der Binärwert mit allen Bits zu 1 repräsentiert den größten Wert. Wie der Name schon sagt, wird der Wert binär (positiv oder negativ) binär mit n Bits mit einer Vorspannung (normalerweise 2 ^ (n-1) oder 2 ^ (n-1) -1) codiert.

Wenn wir also 8 Bits verwenden, wird der Wert 1 in Dezimalzahl in Binärform unter Verwendung einer Vorspannung von 2 ^ (n-1) durch den Wert dargestellt:

+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001
Traumcrash
quelle
2
Meine Frage genau: Werden + ve Nummern gespeichert, binary as iswährend -ve Nummern gespeichert werden two's complement?
Kevin Rave
1
Positive Ganzzahlen werden im Allgemeinen als einfache Binärzahlen gespeichert, und negative Ganzzahlen werden als Zweierkomplement gespeichert.
Dreamcrash
Das beantwortet meine Frage. Irgendeine Quelle? Ich habe kein Dokument gefunden, das dies eindeutig sagt.
Kevin Rave
Der obige Link von ecomware.com ist defekt. @dreamcrash. Können Sie einen anderen Link bereitstellen?
Ram Patra
@ Ramswaroop Hallo, was ist mit diesem einen stackoverflow.com/questions/1049722/what-is-2s-complement
dreamcrash
60

Java-Ganzzahlen bestehen aus 32 Bit und sind immer signiert. Dies bedeutet, dass das höchstwertige Bit (MSB) als Vorzeichenbit fungiert. Die durch an dargestellte Ganzzahl intist nichts anderes als die gewichtete Summe der Bits. Die Gewichte sind wie folgt zugeordnet:

Bit#    Weight
31      -2^31
30       2^30
29       2^29
...      ...
2        2^2
1        2^1
0        2^0

Beachten Sie, dass das Gewicht des MSB negativ ist (das größtmögliche Negativ tatsächlich). Wenn dieses Bit aktiviert ist, wird die ganze Zahl (die gewichtete Summe) negativ.

Simulieren wir es mit 4-Bit-Zahlen:

Binary    Weighted sum            Integer value
0000       0 + 0 + 0 + 0           0
0001       0 + 0 + 0 + 2^0         1
0010       0 + 0 + 2^1 + 0         2
0011       0 + 0 + 2^1 + 2^0       3
0100       0 + 2^2 + 0 + 0         4
0101       0 + 2^2 + 0 + 2^0       5
0110       0 + 2^2 + 2^1 + 0       6
0111       0 + 2^2 + 2^1 + 2^0     7 -> the most positive value
1000      -2^3 + 0 + 0 + 0        -8 -> the most negative value
1001      -2^3 + 0 + 0 + 2^0      -7
1010      -2^3 + 0 + 2^1 + 0      -6
1011      -2^3 + 0 + 2^1 + 2^0    -5
1100      -2^3 + 2^2 + 0 + 0      -4
1101      -2^3 + 2^2 + 0 + 2^0    -3
1110      -2^3 + 2^2 + 2^1 + 0    -2
1111      -2^3 + 2^2 + 2^1 + 2^0  -1

Das Zweierkomplement ist also kein exklusives Schema für die Darstellung negativer Ganzzahlen, sondern wir können sagen, dass die binäre Darstellung von Ganzzahlen immer gleich ist, wir negieren nur das Gewicht des höchstwertigen Bits. Und dieses Bit bestimmt das Vorzeichen der ganzen Zahl.

In C gibt es ein Schlüsselwort unsigned(in Java nicht verfügbar), das zum Deklarieren verwendet werden kann unsigned int x;. In den Ganzzahlen ohne Vorzeichen ist das Gewicht des MSB eher positiv ( 2^31) als negativ. In diesem Fall wird der Bereich eines unsigned intist 0zu 2^32 - 1, während ein intBereich hat -2^31zu 2^31 - 1.

Unter einem anderen Gesichtspunkt, wenn Sie das Zweierkomplement xals ~x + 1(NICHT x plus eins) betrachten, ist hier die Erklärung:

Für jede x, ~xist nur das bitweise Inverse von x, also überall dort , wo xeine hat 1-Bit, ~xeine hat 0-Bit gibt (und umgekehrt). Wenn Sie diese addieren, gibt es keinen Übertrag in der Addition und die Summe ist nur eine ganze Zahl, von der jedes Bit ist 1.

Für 32-Bit-Ganzzahlen:

x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
x + ~x + 1 =   1111 1111 1111 1111 1111 1111 1111 1111 + 1
           = 1 0000 0000 0000 0000 0000 0000 0000 0000

Das 1Bit ganz links wird einfach verworfen, da es nicht in 32-Bit passt (ganzzahliger Überlauf). So,

x + ~x + 1 = 0
-x = ~x + 1

Sie können also sehen, dass das Negative xdurch dargestellt werden kann ~x + 1, was wir das Komplement der beiden nennen x.

0605002
quelle
Meine Frage genau: Werden + ve Nummern gespeichert, binary as iswährend -ve Nummern gespeichert werden two's complement?
Kevin Rave
Nun ja. eine negative Zahl ist dargestellt als das Zweierkomplement seines positiven Wert auf einen Computer.
0605002
4
Tolle Antwort und Erklärung Bonny @ 0605002, +1 :)
KM Rakibul Islam
@ 0605002: Könnten Sie bitte den Verweis auf diese Antwort geben, falls vorhanden? Ich kannte die Konzepte zwar, dachte sie aber nie wirklich so. Einfachste, immer noch genaue Antwort.
Abhishek Singh
Vier Jahre Universität, und ich habe 2s Ergänzung nie verstanden. Diese Antwort hat mich mehr gelehrt. Es ist so traurig, dass so einfache Dinge auf der ganzen Welt auf so arkane Weise gelehrt werden.
Prashant Pandey
10

Ich habe das folgende Programm ausgeführt, um es zu wissen

public class Negative {
    public static void main(String[] args) {
        int i =10;
        int j = -10;

        System.out.println(Integer.toBinaryString(i));
        System.out.println(Integer.toBinaryString(j));
    }
}

Ausgabe ist

1010
11111111111111111111111111110110

Aus der Ausgabe geht hervor, dass das Zweierkomplement verwendet wurde.

Dungeon Hunter
quelle
1
Zweierkomplement von 10 ist 11111111 11111111 11111111 11110110. Ihre Drucke, während Binär wie für 10 1010 ist. Also werden nur -ve Zahlen als Zweierkomplement gespeichert?
Kevin Rave
Überprüfen Sie den Wiki-Artikel en.wikipedia.org/wiki/… Die 2-Komplement-Nummer, die Sie für 15 angegeben haben, ist falsch
Dungeon Hunter
Wenn das MSB-Bit mit 1 beginnt, ist es eine negative Zahl
Dungeon Hunter
Ja, das Zweierkomplement von 10 ist 11111111 11111111 11111111 11110110, was -10 ist
Dungeon Hunter
+ ve Zahlen werden als binär gespeichert, wobei das Vorzeichenbit im 2er-Komplement verbleibt
Dungeon Hunter
4

Oracle bietet einige Dokumentationen zu Java- Datentypen , die Sie möglicherweise interessant finden. Speziell:

int: Der Datentyp int ist eine 32-Bit-Zweierkomplement-Ganzzahl mit Vorzeichen. Es hat einen Mindestwert von -2.147.483.648 und einen Höchstwert von 2.147.483.647 (einschließlich).

Übrigens wird kurz auch als Zweierkomplement gespeichert.

matsev
quelle
3

Gemäß diesem Dokument werden alle Ganzzahlen signiert und im Zweierkomplementformat für Java gespeichert. Nicht sicher von seiner Zuverlässigkeit ..

Joel
quelle
"Im Zweierkomplementformat wird ein positiver Wert als einfache Binärzahl dargestellt." geschrieben im selben Dokument .. also technisch ist es dann richtig. :)
Shashi
3

Positive Zahlen werden so wie sie sind gespeichert / abgerufen.

e.g) For +ve number 10; byte representation will be like 0-000 0010 
                                               (0 - MSB will represent that it is +ve).
So while retrieving based on MSB; it says it is +ve, 
so the value will be taken as it is. 

Negative Zahlen werden jedoch nach dem 2er-Komplement (außer dem MSB-Bit) gespeichert, und das MSB-Bit wird auf 1 gesetzt.

zB) beim Speichern von -10 dann

  0-000 0010  -> (1's complement) -> 0-111 1101 
              -> (2's complement) 0-111 1101 + 1 -> 0-111 1110
  Now MSB will be set to one, since it is negative no -> 1-111 1110

Beim Abrufen wurde festgestellt, dass MSB auf 1 gesetzt ist. Es ist also negativ, nein. Und das Komplement von 2 wird anders als MSB durchgeführt.

  1-111 1110  --> 1-000 0001 + 1 --> 1-000 0010
  Since MSB representing this is negative 10 --> hence  -10 will be retrived.

Casting

Beachten Sie auch, dass beim Umwandeln von int / short in Byte nur das letzte Byte zusammen mit dem MSB des letzten Bytes berücksichtigt wird.

Nehmen Sie das Beispiel "-130" kurz, es könnte wie unten gespeichert werden

(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110

Jetzt hat das Byte-Casting das letzte Byte genommen, das 0111 1110 ist. (0-MSB) Da MSB sagt, dass es + ve Wert ist, wird es so genommen, wie es ist. Welches ist 126. (+ ve).

Nehmen Sie ein anderes Beispiel "130" kurz, es könnte wie unten gespeichert werden

  0-000 000 1000 0010     (MSB = 0)

Jetzt hat das Byte-Casting das letzte Byte genommen, das 1000 0010 ist. (1 = MSB) Da MSB angibt, dass es sich um einen -ve-Wert handelt, wird das Komplement von 2 ausgeführt und eine negative Zahl zurückgegeben. In diesem Fall wird -126 zurückgegeben.

 1-000 0010  -> (1's complement) -> 1-111 1101 
             -> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
               = -126

Diff zwischen (int) (char) (Byte) -1 UND (int) (kurz) (Byte) -1

(byte)-1       -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111
(char)(byte)-1 -> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

ähnlich

(short)(byte)-1-> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

Aber

(int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111  = 65535
since char is unsigned; MSB won't be carry forwarded. 

UND

(int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
since short is signed; MSB is be carry forwarded. 

Verweise

Warum wird das Zweierkomplement verwendet, um negative Zahlen darzustellen?

Was ist "2's Complement"?

Kanagavelu Sugumar
quelle
2

Das höchstwertige Bit (32.) zeigt an, dass die Zahl positiv oder negativ ist. Wenn es 0 ist, bedeutet dies, dass die Zahl positiv ist und in ihrer tatsächlichen Binärdarstellung gespeichert wird. Wenn es jedoch 1 ist, bedeutet dies, dass die Zahl negativ ist und in der Zweierkomplementdarstellung gespeichert wird. Wenn wir also dem 32. Bit eine Gewichtung von -2 ^ 32 geben, während wir den ganzzahligen Wert aus seiner binären Darstellung wiederherstellen, erhalten wir die tatsächliche Antwort.

Sazzadur Rahaman
quelle
1
Willkommen bei StackOverflow! : D
0605002
2

Vielen Dank, dreamcrash für die Antwort https://stackoverflow.com/a/13422442/1065835 ; Auf der Wiki-Seite geben sie ein Beispiel, das mir geholfen hat, die binäre Darstellung des negativen Gegenstücks einer positiven Zahl herauszufinden.

Bei Verwendung von 1 Byte (= 2 Halbbytes = 8 Bits) wird beispielsweise die Dezimalzahl 5 durch dargestellt

0000 01012 Das höchstwertige Bit ist 0, daher repräsentiert das Muster einen nicht negativen Wert. Um in Zweierkomplementnotation in -5 umzuwandeln, werden die Bits invertiert; 0 wird 1 und 1 wird 0:

1111 1010 Zu diesem Zeitpunkt ist die Ziffer das Einsenkomplement des Dezimalwerts −5. Um das Zweierkomplement zu erhalten, wird 1 zum Ergebnis addiert, was Folgendes ergibt:

1111 1011 Das Ergebnis ist eine vorzeichenbehaftete Binärzahl, die den Dezimalwert −5 in Zweierkomplementform darstellt. Das höchstwertige Bit ist 1, daher ist der dargestellte Wert negativ.

Maksim Dmitriev
quelle
1

positive Zahlen werden direkt als binär gespeichert. Das Kompliment von 2 ist für negative Zahlen erforderlich.

beispielsweise:

15: 00000000 00000000 00000000 00001111
-15: 11111111 11111111 11111111 11110001

Hier ist der Unterschied im vorzeichenbehafteten Bit.

Siva Padhy
quelle
1

Für eine positive ganze Zahl 2 ist der Komplementwert mit dem MSB-Bit 0 identisch (like +14 2'complement is 01110).

Nur für eine negative ganze Zahl berechnen wir den 2'-Komplementwert (-14= 10001+1 = 10010).

Die endgültige Antwort lautet also, dass beide Werte (+ve and -ve)nur in 2'-Komplementform gespeichert sind.

Mangesh Gawali
quelle