2009-06-30 14 views
1

Ich bin eine Funktion kurze GetBITS (kurze Daten, int p, int n) schreibeneine Funktion: kurze GetBITS (kurze Daten, int p, int n)

Ich habe versucht:

public static short getBits(short data, int p, int n) { 
    short bitmask = (short) ((~0 << (16 -n)) >>> p); 
    short returnVal = (short) ((bitmask & data) >>> (16 - n)); 
    return returnVal; 
} 

Dies funktioniert für getBits ((kurz) 0x7000, 0, 4), aber wenn ich die 7 durch eine 8 ersetzen würde, bekomme ich einen negativen Wert.

Antwort

2

Es gibt ein paar Dinge, die man sich über Java-Datentypen merken sollte, damit dieses Ding funktioniert.

Ich gehe davon aus, dass Sie Int-Variablen verwenden, weil explizite Umwandlungen in Ihrem Ausdruck fehlen. Wenn Sie einen int-Typ für Ihre Variablen verwenden: data start_pos und length; Sie sollten 32 statt 16 verwenden, da int 32-Bit-Werte sind.

Auch wenn Sie ganzzahlige primitive Typen wie int, short oder byte verwenden, denken Sie daran, dass diese primitiven Typen Zweierkomplemente sind, die vorzeichenerweitert sind, was bedeutet, dass Sie bei negativen Zahlen wie ~ 0 eine Rechtsverschiebung vornehmen (wird zu -1 ausgewertet), werden Einsen an das höherwertige Bit (Vorzeichenbit) anstelle von Nullen angehängt.

Zum Beispiel:

1111 1111 1111 1111 1111 1111 1111 1000   
>>1 
1111 1111 1111 1111 1111 1111 1111 1100 

jetzt zum Problem zurück. Die allgemeine Idee ist in der Lage sein, ein zu tun:

data & mask 

Nun ist die Maske zu erzeugen ein bisschen schwierig auf signierte Datentypen. Es wäre sinnvoll, um die Maske zu erzeugen, mit:

(~0 << (32 - length) >> (32 - length - start_pos)) 

Aber das wird nicht wegen der Vorzeichenerweiterung natürlich arbeiten.

Ich würde vorschlagen, anstelle der rechten Verschiebung >>, drehen Sie den Operator >>> auf diese Weise anstelle von denen an das höherwertige Bit angehängt werden, wird der Drehoperator das Bit niedrigerer Ordnung anhängen.

Zum Beispiel:

1111 1111 1111 1111 1111 1111 1111 1000   
>>>1 
0111 1111 1111 1111 1111 1111 1111 1100 

so ...

mask = (~0 << 32-length >>> 32-length-start_pos) 

Und Ihre endgültige Antwort würde wie etwas aussehen:

(data & (~0 << 32-length >>> 32-length-start_pos)) >>> start_pos 

der äußerste Drehvorgang bewegt sich Ihre maskierten Daten zu die Bits niedrigerer Ordnung.

+0

Vielen Dank! Nachdem ich meine Frage geklärt und Ihre Antwort verwendet hatte, kam ich auf diese: zurück (kurz) ((Daten >>> (16-p-n)) & ((1 << n) -1)) Was funktioniert perfekt! – powerj1984

+0

@ powerj1984 - Die OP scheint "p" gemein zu haben; Zählen von den am wenigsten signifikanten Bits. Ihre Lösung würde funktionieren, wenn Sie meinen; Zählen von dem höchstwertigen Bit. –

+1

Wäre toll, Ihre Frage so zu formulieren, wie sie von theis anwser gelöst wird. Woanders wird StackOverflow bald zu einem Stapel von unbewältigten Fragen werden. – Riduidel

1

Nicht sicher, warum Sie kurz verwenden müssen. Hier ist eine Lösung mit langen.

public static long getBits(long data, int p, int n) { 
    assert p >= 0 && p < 64; 
    assert n >= 0 && n < 64; 
    return (data >> p) & ((1 << n) - 1); 
}