2009-09-22 30 views
14

Aralarında bir döngü kullanmadan, 1 bit sayısına sahip olmak için bir yönteme bakıyorum. herhangi bir vücut bana yardımcı olabilir ve bana kod ya da algoritma bunu yapmak için sağlayabilir. Şimdiden teşekkürler. Bit Twiddling Hacks1 sayısı 32 bit sayısı

+2

örn JDK 1.5 uygulamasıdır 2344'ten 2,3,4,4'e kadar ister misin? Lütfen giriş ve gerekli çıkış ile netleştirin –

cevap

8

standart referans bakınız bit sayısı kümesine sayı. Dört sonucu ekleyin, presto!

Ayrıca Mitch Buğday söylediklerini görmek - Bit işe yaramaz eğlenceli olabilir;)

+2

Sadece Java girişlerinin * her zaman * imzalandığını ve buna göre değiştireceğinizi unutmayın. – erickson

3

Bölünmüş dört 8 bit numaraları içine 32 bitlik bir sayı (döküm bit operatör kaydırma vb bakınız)

sonra 8 bit dönüştürür 256 kayıt girişine sahip bir arama kullanımı:

43

nasıl çalıştığını görmek istiyorsanız Integer.bitCount(int). Sen kaynak koduna başvurabilirsiniz bakın; Integer sınıfının bit Raketi çevirmek rutinleri birçok Sen yinelemeli bunu tanımlayabilir Hacker's Delight.

+4

Evet! Zaten mevcut bir yöntem olduğunda, neden bir egzotik bit hack kullanın. – Buhb

+4

Yerleşik kullanımı, JVM'nin gelecekteki sürümlerinin SSE4.2 POPCNT komutunun bunun için kullanılabileceğini anlamasını da kolaylaştıracaktır. JRE yöntemi için –

+0

+1. Partiyi bozmak için –

3

alınmıştır:

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

Yukarıdaki kod test değildir ve muhtemelen sadece x> = 0 için çalışır. Umarım, Bit Twiddling Hacks doğrudan neyse fikri ...

+2

-1. Elbette, bir döngü yapısı kullanmıyor, ancak hala O (1) olmayan bir zamanda çalışıyor. – unwind

+2

Üzgünüm. Soru bana bir ev ödevi problemini andırdı ve ben farklı bir görüş sağlamak istedim. Teorik olmayan uygulamaların yanı sıra kritik performanslar için, bit-twiddling çözümleri için gidin! – SteinNorheim

+0

klasik olan: dönüş (x == 0)? 0: (1 + bit sayısı (x & (x - 1))); – Olexiy

3

Benim kişisel favori alacak:

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

NB: Bu, Java'nın imzalı int türüyle doğru şekilde çalışmaz - ancak temel fikir kütüphane tarafından kullanılanıdır. – erickson

+1

Sanırım >>> yerine >>>. – finnw

+0

@finnw: Sanırım Java'da kastediyorsunuz (çünkü C'de böyle bir operatör yok, bu numarayı ilk gördüğüm/kullandım), bu durumda haklısınız, işaretin yanlış kalmasını sağlayın. –

4

Kısa, müstehcen optimize cevap (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; 
} 

nedenini öğrenmek için Bu sihir, 'un Güzel Kodu numaralı telefondan Henry S. Warren, Jr. Ardından

+0

Ama soru Java ile ilgili ve Java'da imzasız 32 bit int türü yok ve bu Java'nın imzalı 32 bit int ile çalışmıyor. . – Jesper

+0

Görebildiğim kadarıyla, söz konusu Java'dan bahsedilmiyor. Belki de yanıldım, ancak bir soruyu belirli bir dile sınırlamak için etiket kullanılmamalıdır. – lindelof

+6

IMO yanılıyorsunuz. Bir soru Java ile etiketlenmişse, başka bir soru, bunun Java ile ilgili sorusu dışında ne anlama geliyor? Belki de soru soran, Java hakkında konuştukları metinden de bahsetmeli, ancak eğer yapmazlarsa, bunu Java olarak etiketlemediğini iddia etmemiz gerektiğini düşünmüyorum. Bir C cevabının kabul edilebilir olduğunu kabul ederseniz, bir GCC'ye sadece C yanıtının kabul edilebilir olduğunu ve __builtin_popcount'u kullanacağını söyleyebilirim. Ancak bu soruya çok fazla yardımcı olmuyor ;-) –

2

Integer.bitCount

arasında
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; 
}