2009-09-22 10 views
14

Szukam metody numer 1 w 32 bitowym numerze bez użycia pętli pomiędzy. może pomóc dowolne ciało i dostarczyć mi kod lub algorytm , aby to zrobić. Z góry dzięki.liczba 1 w 32 bitowym numerze

+2

np chcesz polubić od 2344 do 2,3,4,4? proszę wyjaśnić, wprowadzając dane wejściowe i wymagane dane wyjściowe. –

Odpowiedz

8

Patrz kanonicznej odniesienia: Bit Twiddling Hacks

+2

Należy pamiętać, że elementy wewnętrzne Java są zawsze * podpisane i odpowiednio zmodyfikowane. – erickson

3

rozdzielać liczba 32-bitowa w czterech 8-bitowych liczb (patrz nieco przesuwa operatora, odlewanie itp)

Następnie za pomocą odnośnika z 256 wpisów, które przetwarza 8 bit liczba do liczby zestawów bitów. Dodaj cztery wyniki, presto!

także zobaczyć, co powiedział Mitch Wheat - nieco błahy może być dużo zabawy;)

43

Zobacz Integer.bitCount(int). Można odwołać się do kodu źródłowego, jeśli chcesz zobaczyć, jak to działa; wielu z rutyny nieco twiddling klasy za Integer są pobierane z Hacker's Delight.

+4

Tak! Po co używać egzotycznego hackowania, gdy istnieje już dostępna metoda. – Buhb

+4

Użycie wbudowanego ułatwi również przyszłym wersjom JVM zrozumienie, że do tego celu można użyć instrukcji POPCNT SSE4.2. –

+0

+1 dla metody JRE. –

3

Można go zdefiniować rekurencyjnie:

int bitcount(int x) { 
    return (x==0) ? 0 : (x & 1 + bitcount(x/2)); 
} 

Powyższy kod nie został przetestowany i prawdopodobnie działa tylko dla x> = 0. Mamy nadzieję, że dostaniesz pomysł Anyways ...

+2

-1 dla użycia rekursji, gdy zażądano "braku pętli". Oczywiście, nie używa on konstrukcji pętli, ale nadal działa w czasie innym niż O (1). – unwind

+2

Przepraszamy. Pytanie to przypominało mi zadanie domowe i chciałem przedstawić inny pogląd. W przypadku aplikacji krytycznych zarówno pod względem wydajności, jak i większości zastosowań nie-teoretycznych, warto sięgnąć po rozwiązania typu "bit-twiddling"! – SteinNorheim

+0

klasyczna to: powrót (x == 0)? 0: (1 + bitcount (x & (x - 1))); – Olexiy

3

mój osobisty faworyt, bezpośrednio z Bit Twiddling Hacks:

v = v - ((v >> 1) & 0x55555555); 
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; 
+0

NB: To nie będzie działać poprawnie z typem int podpisanym przez Javę - ale podstawowym pomysłem jest ten używany przez bibliotekę. – erickson

+1

Myślę, że chcesz >>> zamiast >>. – finnw

+0

@finnw: Przypuszczam, że masz na myśli w Javie (ponieważ nie ma takiego operatora w C, gdzie pierwszy raz zobaczyłem/wykorzystałem sztuczkę), w takim przypadku masz rację, utrzymywanie znaku jest błędne. –

4

krótki, nieprzyzwoicie zoptymalizowaną odpowiedź (w C):

int pop(unsigned x) { 
    x = x - ((x >> 1) & 0x55555555); 
    x = (x & 0x33333333) + ((x >> 2) & 0x33333333); 
    x = (x + (x >> 4)) & 0x0F0F0F0F; 
    x = x + (x >> 8); 
    x = x + (x >> 16); 
    return x & 0x0000003F; 
} 

Aby zrozumieć, dlaczego ta magia działa, patrz: Quest for Accelerated Population Count autorstwa Henry S. Warren, Jr. rozdział 10 w Piękny kod.

+0

Ale pytanie dotyczyło Java, aw Javie nie ma niepodpisanego 32-bitowego typu int, a to nie działa z podpisem 32-bitowym w języku Java . – Jesper

+0

O ile widzę, Java nie jest wymieniona w pytaniu. I może się mylę, ale tagi nie powinny być używane do ograniczania pytania do danego języka. – lindelof

+6

IMO jesteś w błędzie. Jeśli pytanie jest oznaczone językiem Java, co jeszcze to oznacza, poza tym pytanie dotyczy języka Java? Może pytający powinien także wspomnieć w tekście, że mówią o Javie, ale jeśli nie, to nie sądzę, że powinniśmy udawać, że to nie jest oznaczona Java. Jeśli możesz przyjąć, że odpowiedź na C jest akceptowalna, to mogę przyjąć, że odpowiedź C na GCC jest akceptowalna i że użyję __builtin_popcount. Ale to nie pomaga zbytnio pytającemu ;-) –

2

Poniżej JDK 1,5 realizacja z Integer.bitCount

public static int bitCount(int i) { 
    // HD, Figure 5-2 
i = i - ((i >>> 1) & 0x55555555); 
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); 
i = (i + (i >>> 4)) & 0x0f0f0f0f; 
i = i + (i >>> 8); 
i = i + (i >>> 16); 
return i & 0x3f; 
} 
Powiązane problemy