2013-08-06 9 views
7

I trzeba wyodrębnić pewne nieco waha się od z długim wartości, na przykład:Java dostać zakresy bitowych z długim

long input = 15367 (11110000000111) 

Co muszę wtedy zrobić, to wyodrębnić dwa długie wartości od oryginału długo,

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) 

wiem, można to zrobić z nieco przesunięcia i maskowanie, jednak nie jestem do końca pewien, jak wdrożyć, że tak to dynamiczny za każdym razem, jak za każdym razem muszę to zrobić, długo będzie inna , a także będzie określony zakres bitów.

Czytałem o BitSetach i BitArray, jednak nie jestem do końca pewien, czy są to odpowiednie rzeczy do wykonania tej pracy.

Wszelkie porady na temat najlepszego sposobu realizacji tego będą bardzo mile widziane.

Dzięki!

Odpowiedz

8

Aby wyodrębnić nrBits bitów, począwszy od offsetu offset, można zrobić:

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; 
} 

Uwaga użytkownik prawej operatora przesunięcia >>>; to dlatego, że nie masz przy sobie trochę znaku.

Jeśli chodzi o (1L << nrBits) - 1L, czyli 2^nrBits - 1. L ma mieć stałe long.

Należy również pamiętać, że nie ma "sprawdzania ograniczeń" (na przykład przesunięcie lub liczba bitów większa niż 63 lub ujemna).

+0

tylko bilet, dzięki FGE! – Tony

+1

Czy ">>" nie działałoby, ponieważ '&' na końcu usunie znak rozszerzony '1's? (Przypadek rogu na twoją korzyść: wyodrębniasz bity poza lewe skrajne wejście, np. nrBits = 32, przesunięcie> 32) – zapl

+0

Nie, nie byłoby. Powiedz (z 8 bitami, aby uprościć), że masz '10001111' i chcesz wyodrębnić trzy bity zaczynając od przesunięcia 3: jeśli użyjesz' >>> ', prawe przesunięcie daje' 00010001', ale z '>>' byłoby daj "11110001" (bit znaku jest przenoszony). – fge

2

Aby wyodrębnić bitów między bit x i y bitowej, gdzie x jest większy z dwóch liczb, można powiedzieć

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

Zamiast 'pow (2, n)' możesz użyć '1 << n'. Prawdopodobnie masz na myśli '&' zamiast '&&'. – arshajii

+0

Przepraszam, singiel i, masz rację - naprawiony. Przesunięcie pozycji 1 n jest również dobre, prawdopodobnie szybsze. – user1111284

+0

Dzięki user1111284! – Tony