Verschiebeoperatoren - manchmal falsche Ergebnisse

  • Themenstarter Themenstarter Karl123
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
K

Karl123

Gast
Hallo,
seit einiger Zeit versuche ich Big-Endian in Little-Endian zu konvertieren.
Nun glaubte ich eine Lösung gefunden zu haben: mit Verschiebeoperatoren.

Nach ausgiebigem Test musste ich leider feststellen, dass manchmal falsche Werte geliefert werden.

Wo liegt der Fehler und wie kann ich ihn eliminieren?

Hier mein Programm mit einem der wenigen Werte, der falsch berechnet wird:

Code:
public class LendianShort
{
        public static void main(String[] args)
        {
          int i = 18953;
          String hex = Integer.toHexString(i);

          System.out.println("hex = "+hex);
          System.out.println("hexLittleEndian = "+Integer.toHexString(swabInt(i)));
          	String hexLE = Integer.toHexString(swabInt(i));
          	String hexLEShort = hexLE.substring(0,4);
          
          System.out.println("hexLEShort = "+hexLEShort +" i="+i);
          
        }

        public final static int swabInt(int v) {
                return  (v >>> 24) | (v << 24) | ((v << 8) & 0x00FF0000) | ((v >> 8) &
0x0000FF00);
        }
}

Kommentar: Die Dezimalzahl 18953 liefert die hex-Zahl 4a09 (Big Endian). Die entsprechende Little-Endian-Zahl sollte 094a lauten. Geliefert wird die fehlerhafte Zahl 94a0. Möglicherweise hängt das Problem mit der führenden Null zusammen.
Leider finde ich nur sehr spärlich Literatur zur Arbeitsweise der o.g. Vergleichsoperatoren. Daher kann ich das Beispiel nicht im Detail nachvollziehen.
Ausserdem gibt es kein Short.toHexString, daher der Umweg über Integer.

Ein ähnliches Beispiel findet sich unter http://www.codeguru.com/java/articles/366.shtml. Es arbeitet ebenso unkorrekt.
 
Wie viele Bits willst du denn verdrehen? Willst du alle Bytes in einem int oder alle in einem short umdrehen? Oder nur die unteren 16 Bits eines ints umdrehen, als wäre es ein short?

Code:
// alle in int umdrehen
int alt = irgendwas;
int umgedreht = alt << 24 | (alt & 0xFF00) << 8 | (alt & 0xFF0000) >>> 8 | alt >>> 24;

// alle in short umgedreht
short alt = irgendwas;
short umgedreht = alt >>> 8 | alt << 8;

// untere 16 Bit in int ist identisch mit allen in short
Ungetestet!

Ark
 
Ich möchte erreichen, daß short-Zahlen (Wertebereich -32768 bis +32767), welche als Dezimalzahlen mit Vorzeichen eingegeben werden, als Little-Endian (String) ausgegeben werden.

Hierzu ein weiteres Beispiel:

Eingabe: 30540

Ausgabe Big-Endian (String) wäre: 77 4c
Ausgabe Little-Endian (String): 4c 77

Also, die beiden Bytes werden vertauscht.

Es soll noch eine elegantere Methode geben, bei der ich es leider nicht schaffe, sie in mein Programm einzubauen:

// nio access to little-endian binary float data
float f = ByteBuffer.wrap( array ).order( ByteOrder.LITTLE_ENDIAN ).getFloat();
Quelle: http://mindprod.com/jgloss/endian.html

Gut dokumentierte Beispiele lassen sich im Internet leider nicht finden.
 
Das geht so:

Code:
short s = 18953;
short rev = Short.reverseBytes(s);

System.out.printf("%04x\n",s);
System.out.printf("%04x\n",rev);
 
Danke shad0w für die kurze und elegante Methode die short-Bytes zu vertauschen.

Doch wie kann ich jetzt aus "short rev" einen "String rev" machen? Es gibt ja kein "Short.toHexString" sondern nur "Integer.toHexString".
 
Ich kann nach meiner alten Methode "short" über "integer" via "Integer.toHexString" in den gewünschten Hex-String umwandeln.

Doch dann gehen mir wieder die führenden Nullen verloren, was bei der weiteren Verarbeitung zu Fehlern führen würde.

Wie kann ich die führenden Nullen erhalten?

Code:
public class LendianShort2
{
        public static void main(String[] args)
        {
        short s = 18953;
	short rev = Short.reverseBytes(s);

	int revInt = (int)rev;
	String hex = Integer.toHexString(revInt);
	
	System.out.printf("%04x\n",s);
	System.out.printf("%04x\n",rev);
	System.out.println(hex);
	
	}

Ausgabe:

4a09
094a
94a (falsch, gewünscht ist 094a als String)
 
mit String.format() kannst du auch einen String erstellen statt nur eine Konsolenausgabe
 
Prima! Danke SlaterB für den Hinweis!

So funktioniert die Umwandlung, wie ich sie brauche:

Code:
public class LendianShort2
{
        public static void main(String[] args)
        {
        short s = 18953;
	short rev = Short.reverseBytes(s);

	String hex = String.format("%04x\n",rev);
	
	System.out.printf("%04x\n",s);
	//System.out.printf("%04x\n",rev);
	System.out.println(hex);
	
	}


}

Ergebnis:

4a09
094a (jetzt als Hex-String)
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben