2010-05-23 10 views
8

Jeśli masz numer binarny 10110, w jaki sposób mogę go uzyskać, aby zwrócić 11111? na przykład nowy numer binarnym, który ustawia wszystkie bity na 1 po pierwszym 1, istnieją podobnie przykłady podane poniżej:Uzyskaj długość bitów użytych w int

101 powinna powrócić 111 (o długości 3 bitów) 011 powinna powrócić 11 (długość dwóch bitów) 11100 powinna be return 11111 (długość 5 bitów) 101010101 powinien powrócić 111111111 (długość 9 bitów)

Jak można uzyskać ten najprostszy sposób w Javie? Mogę wymyślić kilka metod, ale nie są one bardzo "ładne".

+3

To wszystko jest tutaj: http://graphics.stanford.edu/~seander/bithacks.html –

Odpowiedz

6

Można użyć tego kodu:

int setBits (int value) 
{ 
    value |= (value >> 1); 
    value |= (value >> 2); 
    value |= (value >> 4); 
    value |= (value >> 8); 
    value |= (value >> 16); 
    return value; 
} 

Chodzi o to, że od lewej 1 zostaną skopiowane do wszystkich pozycjach prawo.

EDYCJA: Działa również dobrze z ujemnym value. Jeśli zastąpisz int przez long, dodaj jedną dodatkową instrukcję: |=: value |= (value >> 32). Ogólnie rzecz biorąc, ostatnia zmiana musi być potęgą 2, która jest co najmniej w połowie rozmiaru value w bitach.

+2

Co jest szczególnie miłe z tym algorytmem, to że ponownie wykorzystuje wcześniejsze operacje. Naiwnie po prostu zrobiłbym 32 zmiany. –

+1

Jeśli spojrzysz na implementację 'Integer # highestOneBit()' w JDK, zobaczysz ten sam algorytm, chociaż ostatni krok jest dostosowany, dostarczaj tylko jeden bit, wymagając cofnięcia przechwyconego w odpowiedzi hleinone. – seh

6

nie testowałem, ale coś jak to powinno być w porządku:

long setBits(long number) { 
    long n = 1; 
    while (n <= number) n <<= 1; 
    return n - 1; 
} 
+0

+1 do nieszablonowego myślenia :-) –

+1

To nie działa, jeśli ' liczba' jest ujemna. Będzie szybko, jeśli "liczba" jest zwykle mała, ale powolna, jeśli "liczba" jest równomiernie rozłożona na swoim zasięgu. – doublep

+0

Prawda o negatywach, nie myślałem o tym. I byłoby średnio szybciej, gdybym zaczął od drugiego końca. Ale 63 iteracje (max) nie są tak powolne; a odpowiedź była na wierzchu mojej głowy. Oczywiście, roztwór hleinonu wydmuchuje go z wody ... :) – Amadan

0

nie najbardziej skuteczny, ale najprostszy,

int i = (1 << (int)(Math.log(n)/Math.log(2)+1)) - 1; 

Będzie pracować dla pierwszej 31 bit int i pierwsze 63 bitów na długo.

10
+0

Dla kompletności: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Integer.html#highestOneBit(int) – Eric

+0

Hmmm .. Wygląda na to, że nie mogę opublikować linku. SO nie lubi nawiasów. – Eric

+3

Wow, nie miał pojęcia, że ​​Java ma tę funkcję ... to jest zdecydowanie najbardziej eleagant tutaj. – Amadan

Powiązane problemy