Java-Bytes verstehen

8

Gestern musste ich also eine Anwendung schreiben, um die Seiten in einer AFP-Datei zu zählen. Also habe ich meine MO: DCA spec PDF entstaubt und das strukturierte Feld BPG (Begin Page) und seine 3-Byte-Kennung gefunden. Die App muss auf einer AIX-Box laufen, also habe ich beschlossen, sie in Java zu schreiben.

Für maximale Effizienz entschied ich, dass ich die ersten 6 Bytes jedes strukturierten Feldes lesen würde und dann die restlichen Bytes in dem Feld überspringen würde. Das würde mich bekommen:

%Vor%

Also überprüfe ich den Feldtyp und inkrementiere einen Seitenzähler, wenn es BPG ist, und ich tue es nicht, wenn es nicht ist. Dann überspringe ich die restlichen Bytes im Feld, anstatt sie zu lesen. Und hier, beim Überspringen (und wirklich in der Feldlänge) habe ich entdeckt, dass Java signierte Bytes verwendet.

Ich habe gegoogelt und eine Menge nützlicher Informationen gefunden. Am nützlichsten war natürlich die Anweisung, eine bitweise & bis 0xff auszuführen, um den vorzeichenlosen int-Wert zu erhalten. Dies war für mich notwendig, um eine Länge zu erhalten, die bei der Berechnung für die Anzahl der zu überspringenden Bytes verwendet werden konnte.

Ich weiß jetzt, dass wir bei 128 anfangen, rückwärts von -128 zu zählen. Was ich wissen möchte, ist, wie die bitweise Operation hier funktioniert - genauer gesagt, wie ich bei einer negativen Zahl zur Binärdarstellung komme.

Wenn ich die bitweise & korrekt verstehe, entspricht Ihr Ergebnis einer Zahl, bei der nur die gemeinsamen Bits Ihrer beiden Zahlen gesetzt sind. Unter der Annahme byte b = -128 hätten wir dann:

%Vor%

Wie also würde ich bei 1000 0000 für -128 ankommen? Wie würde ich die Binärdarstellung von etwas weniger Offensichtlichem wie -72 oder -64 erhalten?

    
Brian Warshaw 02.10.2010, 13:05
quelle

6 Antworten

18

Um die binäre Darstellung einer negativen Zahl zu erhalten, berechnen Sie Zweierkomplement:

  • Erhalte die binäre Darstellung der positiven Zahl
  • Invertiere alle Bits
  • Fügen Sie einen
  • hinzu

Machen wir als Beispiel -72:

%Vor%

Also ist die binäre (8-Bit) Darstellung von -72 10111000 .

Was Ihnen tatsächlich passiert, ist folgendes: Ihre Datei hat ein Byte mit dem Wert 10111000 . Wenn es als vorzeichenloses Byte interpretiert wird (was wahrscheinlich das ist, was Sie wollen), ist dies 88.

Wenn dieses Byte in Java verwendet wird (zum Beispiel, weil read() einen int zurückgibt, oder wegen einer impliziten Heraufstufung), wird es als vorzeichenbehaftetes Byte interpretiert und vorzeichenerregt auf 11111111 11111111 11111111 10111000 . Dies ist eine Ganzzahl mit dem Wert -72.

Durch UND-Verknüpfung mit 0xff behältst du nur die niedrigsten 8 Bits, also ist deine ganze Zahl jetzt 00000000 00000000 00000000 10111000 , was 88 ist.

    
Grodriguez 02.10.2010, 13:28
quelle
2
  

Was ich wissen möchte ist, wie die bitweise Operation hier funktioniert - genauer gesagt, wie ich bei einer negativen Zahl zur Binärdarstellung komme.

Die binäre Darstellung einer negativen Zahl ist diejenige der entsprechenden positiven Zahl, die mit 1 umgeblättert wird. Diese Darstellung nennt sich Zweierkomplement .

    
sepp2k 02.10.2010 13:15
quelle
1

Ich denke, die Magie hier ist, dass das Byte in einem größeren Container gespeichert wird, wahrscheinlich 32 Bit int. Und wenn das Byte als ein vorzeichenbehaftetes Byte interpretiert wurde, wird es expandiert, um die gleiche Nummer in dem 32-Bit-Int darzustellen, das heißt, wenn das höchstwertige Bit (das erste) des Bytes eine 1 ist, dann in dem 32-Bit-Int die Bits, die von dieser 1 übrig sind, werden ebenfalls auf 1 gesetzt (das liegt an der Art, wie negative Zahlen dargestellt werden, Zweierkomplement).

Nun, wenn Sie & 0xFF that int haben, schneiden Sie diese 1en ab und enden mit einem "positiven" int, das den Bytewert darstellt, den Sie gelesen haben.

    
DarkDust 02.10.2010 13:23
quelle
1

Nicht sicher, was Sie wirklich wollen :) Ich nehme an, Sie fragen, wie man einen vorzeichenbehafteten Multi-Byte-Wert extrahiert? Sehen Sie zuerst, was passiert, wenn Sie ein einzelnes Byte erweitern:

%Vor%

Also wird das Zeichen korrekt auf 32 Bits erweitert, ohne etwas Besonderes zu tun. Das Byte 1000 0000 wird korrekt auf 1111 1111 1111 1111 1111 1111 1000 0000 erweitert. Sie wissen bereits, wie Sie die Vorzeichenerweiterung unterdrücken, indem Sie AND mit 0xFF unterdrücken. Bei Mehrbytewerten möchten Sie nur das Vorzeichen des höchstwertigen Bytes und die weniger signifikanten Bytes, die Sie als vorzeichenlos behandeln wollen (Beispiel: Netzwerkbyte) Reihenfolge, 16-Bit-Wert int):

%Vor%

Sie müssen die Vorzeichenerweiterung jedes Bytes mit Ausnahme des höchstwertigen unterdrücken, um einen vorzeichenbehafteten 32-Bit-Int zu einem 64-Bit-langen zu extrahieren:

%Vor%

Hinweis: In Intel-basierten Systemen werden Bytes oft in umgekehrter Reihenfolge gespeichert (am wenigsten signifikantes Byte zuerst), da die x86-Architektur größere Objekte in dieser Reihenfolge im Speicher speichert. Viele x86-Software verwendet sie auch in Dateiformaten.

    
Durandal 02.10.2010 16:39
quelle
0

Um den vorzeichenlosen Byte-Wert zu erhalten, können Sie entweder.

%Vor%

oder

%Vor%     
Peter Lawrey 02.10.2010 13:11
quelle
0

Für Bytes mit gesetztem Bit 7:

%Vor%

Mathematisch berechnet man bei der Berechnung mit Bytes Modulo 256. Der Unterschied zwischen signed und unsigned besteht darin, dass man für die Äquivalenzklassen unterschiedliche Repräsentanten auswählt, während die zugrunde liegende Repräsentation als Bitmuster für jede Äquivalenzklasse gleich bleibt. Dies erklärt auch, warum Addition, Subtraktion und Multiplikation das gleiche Ergebnis wie ein Bitmuster haben, unabhängig davon, ob Sie mit Ganzzahlen mit oder ohne Vorzeichen rechnen.

    
starblue 02.10.2010 13:29
quelle

Tags und Links