{"id":1372,"date":"2012-06-16T13:02:04","date_gmt":"2012-06-16T11:02:04","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=1372"},"modified":"2012-06-16T13:02:04","modified_gmt":"2012-06-16T11:02:04","slug":"inselupdate-vorzeichenlos-arbeiten","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2012\/06\/inselupdate-vorzeichenlos-arbeiten\/","title":{"rendered":"Inselupdate: Vorzeichenlos arbeiten"},"content":{"rendered":"<p>Bis auf char sind in Java alle integralen Datentypen vorzeichenbehaftet und kodiert im Zweierkomplement. Bei einem byte stehen 8 Bit f\u00fcr die Kodierung eines Wertes zur Verf\u00fcgung, jedoch sind es eigentlich nur 7 Bit, denn \u00fcber ein Bit erfolgt die Kodierung des Vorzeichens. Der Wertebereich ist von -128 bis +127. \u00dcber einen Umweg ist es m\u00f6glich, den vollen Wertebereich auszusch\u00f6pfen und so zu tun, als ob Java vorzeichenlose Datentypen h\u00e4tte.<\/p>\n<p><strong>byte als vorzeichenlosen Datentyp nutzen<\/strong><\/p>\n<p>Eine wichtige Eigenschaft der expliziten Typanpassung bei Ganzzahltypen ist es, dass die \u00fcbersch\u00fcssigen Bytes einfach abgeschnitten werden. Betrachten wir die Typanpassung an einem Beispiel:<\/p>\n<p>int l = 0xABCD6F;<\/p>\n<p>byte b = (byte) 0xABCD<b>6F<\/b>;<\/p>\n<p>System.out.println( Integer.toBinaryString( l ) ); \/\/ 101010111100110101101111<\/p>\n<p>System.out.println( Integer.toBinaryString( b ) ); \/\/ 1101111<\/p>\n<p>Liegt eine Zahl im Bereich von 0 bis 255, so kann ein byte diese durch seine 8 Bit grunds\u00e4tzlich speichern. Java muss jedoch mit der expliziten Typanpassung gezwungen werden, das Vorzeichenbit zu ignorieren. Erst dann entspricht die Zahl 255 acht gesetzten Bits, denn sie mit byte b = 255; zu belegen, funktioniert nicht.<\/p>\n<p>Damit die Weiterverarbeitung gelingt, muss noch eine andere Eigenschaft ber\u00fccksichtigt werden. Sehen wir uns dazu folgende Ausgabe an:<\/p>\n<p>byte b1 = (byte) 255;<\/p>\n<p>byte b2 = -1;<\/p>\n<p>System.out.println( b1 ); \/\/ -1<\/p>\n<p>System.out.println( b2 ); \/\/ -1<\/p>\n<p>Das Bitmuster ist in beiden F\u00e4llen gleich, alle Bits sind gesetzt. Dass die Konsolenausgabe aber negativ ist, hat mit einer anderen Java-Eigenschaft zu tun: Java konvertiert das Byte, welches vorzeichenbehaftet ist, in ein int (der Parametertyp bei toBinaryString() ist int) und bei dieser Konvertierung wandert das Vorzeichen weiter. Das folgende Beispiel zeigt das bei der Bin\u00e4rausgabe:<\/p>\n<p>byte b = (byte) 255;   <br \/>int&#160; i = 255;    <br \/>System.out.printf( &quot;%d %s%n&quot;, b, Integer.toBinaryString(b) );<\/p>\n<p>\/\/ \u20131&#160; 11111111111111111111111111111111   <br \/>System.out.printf( &quot;%d %s%n&quot;, i, Integer.toBinaryString(i) );<\/p>\n<p>\/\/ 255&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 11111111<\/p>\n<p>Die Belegung der unteren 8 Bit vom byte b und int i ist identisch. Aber w\u00e4hrend beim int die oberen 3 Byte wirklich null sind, f\u00fcllt Java durch die automatische Anpassung des Vorzeichens bei der Konvertierung von byte nach int im Zweierkomplement auf die oberen drei Byte mit 255 auf. Soll ohne Vorzeichen weitergerechnet werden st\u00f6rt das. Diese Automatisch Anpassung nimmt Java immer vor, wenn mit byte\/short gerechnet wird und nicht nur wie in unserem Beispiel, wenn eine Methoden den Datentyp int fordert.<\/p>\n<p>Um bei der Weiterverarbeitung einen Datenwert zwischen 0 und 255 zu bekommen, also das Byte eines int vorzeichenlos zu sehen, schneiden wir mit der Und-Verkn\u00fcpfung die unteren 8 Bit heraus \u2013 alle anderen Bits bleiben also ausgenommen:<\/p>\n<p>byte b = (byte) 255;<\/p>\n<p>System.out.println( b ); \/\/ -1<\/p>\n<p>System.out.println( b &amp; 0xff ); \/\/ 255<\/p>\n<p><strong>Bibliotheksmethoden f\u00fcr vorzeichenlose Behandlung<\/strong><\/p>\n<p>Immer ein &amp; 0xff an einen Ausdruck zu setzen um die oberen Bytes auszublenden ist zwar nicht sonderlich aufw\u00e4ndig, aber sch\u00f6n ist das auch nicht. H\u00fcbscher sind Methoden wie toUnsignedInt(byte), die mit dem Namen deutlich dokumentieren, was hier eigentlich passiert. In Java 8 gibt es daher einige Neuerungen.<\/p>\n<p>Neue Methoden in Byte:<\/p>\n<li>static int toUnsignedInt(byte x)<\/li>\n<li>static long toUnsignedLong(byte x)<\/li>\n<p>In Integer:<\/p>\n<li>static long toUnsignedLong(int x)<\/li>\n<li>static String toUnsignedString(int i, int radix)<\/li>\n<li>static String toUnsignedString(int i)<\/li>\n<li>static int parseUnsignedInt(String s, int radix)<\/li>\n<li>static int compareUnsigned(int x, int y)<\/li>\n<li>static int divideUnsigned(int dividend, int divisor)<\/li>\n<li>static int remainderUnsigned(int dividend, int divisor)<\/li>\n<p>In Long:<\/p>\n<li>String toUnsignedString(long i, int radix)<\/li>\n<li>static String toUnsignedString(long i)<\/li>\n<li>static long parseUnsignedLong(String s, int radix)<\/li>\n<li>static int compareUnsigned(long x, long y)<\/li>\n<li>static long divideUnsigned(long dividend, long divisor)<\/li>\n<li>static long remainderUnsigned(long dividend, long divisor)<\/li>\n<p>In Short:<\/p>\n<li>static int toUnsignedInt(short x)<\/li>\n<li>static long toUnsignedLong(short x)<\/li>\n<p>Neben den einfachen Methoden toUnsignedXXX()-Methoden in den Wrapper-Klassen gesellen sich Methoden hinzu, die auch die Konvertierung in einem String bzw. das Parsen eines Strings erm\u00f6glichen. Bei Integer und Long lassen sich ebenfalls neue Methoden ablesen, die Vergleiche, Division und Restwertbildung vorzeichenlos durchf\u00fchren.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bis auf char sind in Java alle integralen Datentypen vorzeichenbehaftet und kodiert im Zweierkomplement. Bei einem byte stehen 8 Bit f\u00fcr die Kodierung eines Wertes zur Verf\u00fcgung, jedoch sind es eigentlich nur 7 Bit, denn \u00fcber ein Bit erfolgt die Kodierung des Vorzeichens. Der Wertebereich ist von -128 bis +127. \u00dcber einen Umweg ist es [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[11,66],"tags":[],"class_list":["post-1372","post","type-post","status-publish","format-standard","hentry","category-insel","category-java-8"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1372","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=1372"}],"version-history":[{"count":1,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1372\/revisions"}],"predecessor-version":[{"id":1373,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1372\/revisions\/1373"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=1372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=1372"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=1372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}