2013-08-06 27 views
7

ho bisogno di estrarre po 'certa varia da con un lungo valore, ad esempio:Java ottenere intervalli di bit da una lunga

long input = 15367 (11110000000111) 

Che cosa devo quindi fare è estrarre due valori lunghi dalla lunga originale,

First long is 5 bits starting from bit 0, so bits 0:4 = 7 (0111) 
Second long is 56 bits starting from bit 8, so bits 7:55 = 60 (1111000) 

so che questo può essere fatto con po 'di spostamento e mascheramento, però io non sono del tutto sicuro di come implementare che quindi è dinamica di volta in volta, come ogni volta che ho bisogno di fare questo, alla lunga sarà diverso e così pure gli intervalli di bit specifici.

Ho letto di BitSet e BitArray, tuttavia non sono del tutto sicuro che queste siano le cose giuste per il lavoro.

Qualsiasi consiglio sul modo migliore per implementarlo sarebbe molto apprezzato.

Grazie!

risposta

8

Per estrarre nrBits bit a partire da compensare offset, si può fare:

public static long extractSub(final long l, final int nrBits, final int offset) 
{ 
    final long rightShifted = l >>> offset; 
    final long mask = (1L << nrBits) - 1L; 
    return rightShifted & mask; 
} 

Nota l'utente dell'operatore spostamento a destra >>>; questo è così che non porti il ​​segno in giro.

Per quanto riguarda (1L << nrBits) - 1L, ovvero 2^nrBits - 1. Il L deve avere costanti long.

Si noti inoltre che non esiste un "controllo dei limiti" (ad esempio, un offset o un numero di bit maggiore di 63 o negativo).

+0

Solo il biglietto, grazie FGE! – Tony

+1

Non '' '' '' 'funzionante anche perché' & 'alla fine rimuoverà il segno esteso' 1's? (caso d'angolo a tuo favore: estrai bit al di fuori dei limiti più a sinistra del tuo input, ad esempio nrBits = 32, offset> 32) – zapl

+0

No, non lo farebbe. Dì (con 8 bit per semplificare) che hai '10001111' e vuoi estrarre tre bit a partire dall'offset 3: se usi' >>> ', lo spostamento a destra dà' 00010001', ma con '>>' sarebbe diamo '11110001' (il bit del segno è trasportato). – fge

2

Per estrarre i bit tra bit x e y po ', dove x è il più grande dei due numeri, si potrebbe dire

long mask = (Math.pow(2,x+1)-1)- (Math.pow(2,y+1)-1); 
long extract = input & mask; 
+0

Invece di 'pow (2, n)' puoi usare '1 << n'. E probabilmente vuoi dire '&' invece di '&&'. – arshajii

+0

Siamo spiacenti, single e, hai ragione, risolto. Spostare le posizioni 1 n è buono, probabilmente più veloce. – user1111284

+0

Grazie utente1111284! – Tony