Sean Anderson menerbitkan bit twiddling hacks yang berisi algoritma Eric Cole untuk menemukan dari integer bit dalam operasi dengan operasi multiply dan lookup.N v O ( lg ( N ) )
Algoritme bergantung pada nomor "ajaib" dari urutan De Bruijn. Adakah yang bisa menjelaskan sifat matematika dasar dari urutan yang digunakan di sini?
uint32_t v; // find the log base 2 of 32-bit v
int r; // result goes here
static const int MultiplyDeBruijnBitPosition[32] =
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
v |= v >> 1; // first round down to one less than a power of 2
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
r = MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
nt.number-theory
comp-number-theory
Yury Bayda
sumber
sumber
Jawaban:
Perhatikan pertama bahwa algoritma ini hanya menghitung , dan ketika kode ditulis, ia hanya bekerja untuk v yang sesuai dengan kata 32- bit.⌈ log2v ⌉ v 32
Urutan pergeseran dan atau -s yang muncul pertama memiliki fungsi menyebarkan 1-bit terkemuka semua jalan ke bit paling tidak signifikan. Secara numerik, ini memberi Anda 2 ⌈ log 2 v ⌉ - 1 .v 2⌈ log2v ⌉- 1
Bagian yang menarik adalah trik de Bruijn, yang berasal dari makalah Leiserson, Prokop, dan Randall ini (tampaknya para profesor MIT menghabiskan waktu melakukan sedikit peretasan :)). Yang perlu Anda ketahui tentang urutan de Bruijn adalah bahwa mereka mewakili semua urutan yang mungkin dari panjang tertentu dengan cara yang dikompresi mungkin. Tepatnya, urutan de Brujn di atas alfabet adalah string biner dengan panjang 2 k sehingga setiap panjang k string biner muncul tepat sekali sebagai substring yang bersebelahan (pembungkus diijinkan). Alasan ini berguna adalah jika Anda memiliki angka X{ 0 , 1 } s 2k k X representasi bit yang merupakan urutan de Bruijn (diisi dengan nol), maka bit k atas dari 2 i X secara unik mengidentifikasi i (selama i < k ).k k 2sayaX saya saya < k
sumber
Beberapa komentar (bukan jawaban). Mari kita mengklasifikasikan integer 32-bit sebagai berikut:c
Tipe X: (sebagai string biner) adalah urutan De Bruijn (untuk semua rotasi, bit [27,31] berbeda). Sebuah contoh:c
Ketik Y: bit [27,31] dari yang berbeda untuk saya = 0 , 1 , .2saya⋅ c . Inilah yangLeiserson et al. menggunakan. Contoh:i = 0 , 1 , . . . , 31
Ketik Z: bit [27,31] dari berbeda untuk i = 0 , 1 ,( 2i + 1- 1 ) ⋅ c . Inilah yang kita butuhkan dalam pertanyaan awal. Contoh:i = 0 , 1 , . . . , 31
Beberapa pengamatan berdasarkan eksperimen cepat (saya harap ini benar):
Ada 65536 bilangan bulat tipe X.
Ada 4096 bilangan bulat tipe X + Y. Inilah bilangan bulat tipe X yang dimulai dengan urutan '0000 ...'
Ada 256 bilangan bulat tipe X + Y + Z. Inilah bilangan bulat tipe X yang dimulai dengan urutan '0000011111 ...'
Semua bilangan bulat dari tipe Y juga dari tipe X.
Namun, ada juga 768 bilangan bulat tipe Z yang bukan tipe X atau tipe Y. Ini dimulai dengan '1000011111 ...', '0111100000 ...', atau '1111100000 ...'
sumber
Konstanta partikel ini adalah Urutan De Bruijn dengan alfabet Biner tetapi dengan properti tambahan. Saya akan menyebutnya 'Properti Marc Dickinson' karena algoritma asli dapat diimplementasikan tanpa urutan DB khusus ini. Dengan menambahkan 2 operasi tambahan kita bisa menggunakan urutan DB biasa. Operasi: v ^ = (v >> 1); // clr semua bit kecuali MSB yang diatur setelah cascading atau-shift.
Jika Anda berharap untuk rumus matematika yang elegan untuk menggambarkan mereka atau teorema untuk menghasilkan mereka atau sesuatu yang serupa, saya pikir ini akan membutuhkan wawasan mendalam tentang teori bilangan dan mungkin bidang lain yang berada di luar keahlian saya. Jika saya di mana membuat tebakan liar saya harus bertaruh mereka bisa diproduksi oleh automata seluler. Ini bukan jawaban kenapa? pada dasar yang keras tetapi upaya untuk secara intuitif memahami mengapa ia bekerja dan mengapa itu bekerja dengan baik, sehingga Anda dapat menggunakannya dengan percaya diri.
sumber