Set pengepakan non pangkat 2 bilangan bulat

Saya memiliki sekumpulan bilangan bulat, masing-masing dengan rentang tertentu:

foo = [1, 5]
bar = [1, 10]
baz = [1, 200]

Saya dapat menghitung berapa bit yang diperlukan untuk menyimpan setiap angka secara terpisah berdasarkan jumlah status berbeda yang dimilikinya:

foo = 5 possible states   ~ 3 bits
bar = 10 possible states  ~ 4 bits
baz = 200 possible states ~ 8 bits

Yang memberi saya total 15 bit. Namun setiap angka mempunyai rentang yang tidak terpakai sehingga mengakibatkan ruang terbuang sia-sia. Saya malah dapat menghitung bit yang diperlukan untuk keseluruhan rangkaian dengan menghitung semua kemungkinan status dari semua angka yang digabungkan:

5 * 10 * 200 = 10000 possible states ~ 14 bits

Ini bisa menyelamatkanku sedikit!

Dan di sinilah pertanyaan saya muncul: apa cara terbaik untuk memuat dan menyimpan nomor menggunakan tata letak jenis ini?


person Rick de Water    schedule 22.05.2018    source sumber


Jawaban (1)


Daftar variabel dengan rentang berbeda seperti ini:

foo = [1, 5]
bar = [1, 10]
baz = [1, 200]

Bisakah (hampir?) diartikan sebagai representasi bilangan radix campuran. Jika mereka dimulai dari nol maka korespondensinya akan langsung terjadi, namun karena mereka dimulai dari satu (atau secara umum: jika mereka adalah himpunan kemungkinan yang berhingga), maka mereka harus dipetakan ulang terlebih dahulu, di sini cukup dengan mengurangkan satu untuk konversi ke status "dikemas" dan menambahkan satu kembali saat mendekodekannya lagi.

Pengkodeannya bagus dan mudah, hanya melibatkan operasi murah:

packed = (foo - 1) + 5 * (bar - 1) + (5 * 10) * (baz - 1)

Tentu saja, faktor skala berasal dari jumlah keadaan yang memungkinkan. Setiap elemen perlu dipetakan ulang ke dalam rentang yang berdekatan mulai dari nol, dan kemudian diskalakan berdasarkan produk dari #status elemen sebelumnya, dengan elemen pertama diskalakan dengan 1 (produk kosong). Ngomong-ngomong, perhatikan bahwa [1 .. 5] memiliki 5 negara bagian, bukan 4.

Penguraian kode melibatkan sisa dan pembagian, cara paling sederhana (tetapi bukan yang tercepat secara umum) adalah mengekstraksi digit demi digit:

// extract foo
foo = packed % 5 + 1
// drop foo from packed representation
packed /= 5
// extract bar (which is now the lowest digit in 'packed')
bar = packed % 10 + 1
// drop bar
packed /= 10
// top digit is left over
baz = packed + 1

Untuk contoh yang lebih besar akan lebih efisien untuk terlebih dahulu "memotong" nomor yang dikemas menjadi beberapa bagian terpisah, dan kemudian memecahkan kodenya secara terpisah. Hal ini mencegah adanya rantai panjang operasi yang bergantung, yang secara alami dihasilkan oleh metode digit demi digit.

Bekerja secara langsung dengan representasi yang dikemas umumnya rumit, kecuali untuk menambah dan mengurangi elemen jika Anda tahu bahwa elemen tersebut tidak akan meluap.

person harold    schedule 22.05.2018