Scrivere una funzione: getbits breve (dati short, int p, int n)
Domanda
Sto scrivendo una funzione brevi getbits (dati short, int p, int n)
ho provato:
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;
}
Questo funziona per getbits ((brevi) 0x7000, 0, 4) ma se dovessi sostituire il 7 con 8 ottengo un valore negativo.
Soluzione
Ci sono alcune cose da ricordare sui tipi di dati Java, per fare questo lavoro cosa.
Ti sto assumendo stai usando variabili int a causa della mancanza di cast espliciti nella vostra espressione. Se stai usando un tipo int per le variabili: start_pos dati e la lunghezza; si dovrebbe utilizzare 32, invece di 16, dal momento che int di sono valori a 32 bit.
Anche se avete intenzione di utilizzare i tipi integer primitivi come int, brevi o di byte, ricordate che questi tipi primitivi sono complemento a due che sono segno-esteso, il che significa che se si fa uno spostamento a destra su numeri negativi come ~ 0 ( restituisce -1), quelli saranno aggiunti sul bit di ordine superiore (bit di segno) invece di zeri.
Per esempio:
1111 1111 1111 1111 1111 1111 1111 1000
>>1
1111 1111 1111 1111 1111 1111 1111 1100
Ora tornando al tuo problema. L'idea generale è quella di essere in grado di fare una:
data & mask
Ora, generando la maschera è un po 'complicato sui tipi di dati firmati. Avrebbe senso per generare la maschera utilizzando:
(~0 << (32 - length) >> (32 - length - start_pos))
Ma questo non funzionerà ovviamente a causa della estensione del segno.
Vorrei suggerire che invece di utilizzare shift destro >>, uso ruotare operatore >>> questo modo, invece di quelli accodato sul bit di ordine superiore, l'operatore rotazione aggiungerà il bit di ordine inferiore.
Per esempio:
1111 1111 1111 1111 1111 1111 1111 1000
>>>1
0111 1111 1111 1111 1111 1111 1111 1100
così ...
mask = (~0 << 32-length >>> 32-length-start_pos)
E la tua risposta definitiva potrebbe essere simile a:
(data & (~0 << 32-length >>> 32-length-start_pos)) >>> start_pos
L'operazione di rotazione esterna sposta i dati mascherati ai bit di ordine inferiore.
Altri suggerimenti
Non certo perché è necessario utilizzare breve. Ecco una soluzione che utilizza a lungo.
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);
}