Apa nama untuk menyimpan / mengemas banyak negara boolean menjadi satu nomor?

55

Ini adalah semacam kompresi sederhana di mana Anda menggunakan satu variabel numerik untuk menyimpan banyak status boolean / biner, menggunakan penggandaan dan fakta bahwa setiap angka penggandaan adalah 1 + jumlah dari semua yang sebelumnya.

Saya yakin itu pasti teknik lama dan terkenal, saya ingin tahu apa namanya untuk merujuk dengan benar. Saya telah melakukan beberapa pencarian pada setiap cara yang saya bisa pikirkan untuk menggambarkannya, tetapi tidak menemukan apa pun di luar beberapa artikel blog di mana penulis artikel tampaknya telah menemukan jawabannya sendiri dan tidak tahu harus menyebutnya apa, misalnya ( contoh 1 , contoh 2 ).

Sebagai contoh, berikut ini adalah implementasi yang sangat sederhana yang dimaksudkan untuk menggambarkan konsep:

packStatesIntoNumber () {
  let num = 0
  if (this.stateA) num += 1
  if (this.stateB) num += 2
  if (this.stateC) num += 4
  if (this.stateD) num += 8
  if (this.stateE) num += 16
  if (this.stateF) num += 32
  return num
}

unpackStatesFromNumber (num) {
  assert(num < 64)
  this.stateF = num >= 32; if (this.stateF) num -= 32
  this.stateE = num >= 16; if (this.stateE) num -= 16
  this.stateD = num >= 8; if (this.stateD) num -= 8
  this.stateC = num >= 4; if (this.stateC) num -= 4
  this.stateB = num >= 2; if (this.stateB) num -= 2
  this.stateA = num >= 1; if (this.stateA) num -= 1
}

Anda juga bisa menggunakan operator bitwise, parsing angka 2 dasar, enum ... Ada banyak cara yang lebih efisien untuk mengimplementasikannya, saya tertarik dengan nama pendekatan yang lebih umum.

user56reinstatemonica8
sumber
8
Di C #, ada enums, dan mereka dapat memiliki Flagsatribut. Mereka bisa membuat kode Anda jauh lebih sederhana.
Bernhard Hiller
12
Saya akan menyebutnya "simulasi bidang bit". Ini hampir selalu merupakan ide yang buruk kecuali efisiensi ruang sangat penting.
Kilian Foth
7
@KilianFoth A boolumumnya disimpan sebagai integer 32 bit secara internal. Dengan demikian, pengepakan dapat membuat perbedaan faktor 32. Itu sangat banyak. Maksudku, kita programmer selalu siap untuk membuang setengah dari sumber daya kita, tetapi saya umumnya enggan membuang 97% dari mereka. Faktor pemborosan seperti itu dapat dengan mudah membuat perbedaan antara kemampuan menjalankan kasing yang penting dan kehabisan memori.
cmaster
3
Secara historis, tipikal cara bit mask digunakan untuk mendeklarasikan, mengatur, dan mengambil nilai. Menggunakan shift itu aneh dan bukan ilustrasi terbaik dari pendekatan tersebut.
JimmyJames
3
@ cmaster Alasan bool disimpan seperti itu adalah karena berbagi satu lokasi memori (32 atau 64 bit pada mesin saat ini) bisa sangat buruk untuk kinerja cache kecuali Anda memperhatikan kode bahasa mesin. Jika Anda memiliki jumlah bit yang benar-benar besar, itu mungkin sepadan, tetapi jika tidak, Anda mungkin lebih baik tidak melakukan pra-optimisasi dan hanya mengemas bit-bit tersebut ketika Anda siap mengirim ke jaringan atau disk.
Bill K

Jawaban:

107

Ini paling sering disebut sebagai bidang bit , dan istilah lain yang sering Anda dengar adalah topeng bit , yang digunakan untuk mendapatkan atau menetapkan nilai bit individual atau seluruh bidang bit sekaligus.

Banyak bahasa pemrograman memiliki struktur tambahan untuk membantu dengan ini. Seperti yang dicatat oleh @BernhardHiller dalam komentar, C # memiliki enum dengan flag ; Java memiliki kelas EnumSet .

Glorfindel
sumber
4
Saya akan menafsirkan "bidang bit" sebagai menggunakan fitur bahasa yang memungkinkan bit individu untuk ditugaskan ke bidang struktur daripada melakukannya secara manual dengan operator bitwise.
Peter Green
22
@ PeterGreen Itu akan berbeda dari interpretasi standar.
Eric
1
"Pemetaan Bit" atau "Pemetaan Bit", yang umum digunakan untuk pemrosesan dataset dan array, juga dapat diterapkan dalam kasus ini. Saat mengekstraksi elemen umum dari beberapa set, nilai dapat didekomposisi untuk mengidentifikasi komponen model gabungan. Kami bahkan mengatakan ini digit angka file oktal. Topeng Bit (topeng apa saja) cenderung berupa filter (seperti untuk port IO dan register arah data).
mckenzm
1
C # juga memiliki BitArray, yang memungkinkan menyimpan jumlah bit yang sewenang-wenang dan mengindeksnya (sementara bendera terbatas pada tipe integer dan dimaksudkan untuk digunakan sebagai topeng).
Luaan
Benar; Saya baru saja menyebutkan dua struktur yang paling saya kenal. Mungkin ada lusinan di luar sana, terutama dalam bahasa lain.
Glorfindel
20

Aneh, sedikit istilah yang berbeda di sini, tetapi saya tidak melihat istilah yang langsung terlintas dalam pikiran (dan itu ada dalam judul pertanyaan Anda!) - Pengepakan Bit adalah apa yang selalu saya dengar istilahnya.

Saya pikir ini benar-benar jelas tetapi anehnya ketika saya mencari di google, ini sepertinya adalah istilah yang banyak digunakan tetapi tidak didefinisikan secara resmi (Wikipedia tampaknya mengarahkan kembali ke bidang bit yang merupakan cara untuk melakukan pengepakan bit, tetapi bukan nama untuk proses). Mencari definisi tampaknya mengarah ke halaman ini:

http://www.kinematicsoup.com/news/2016/9/6/data-compression-bit-packing-101

Yang tidak bagus untuk tujuan SO tetapi itu adalah definisi / deskripsi terbaik yang dapat saya temukan termasuk deskripsi ringkas ini: "Pengepakan bit adalah konsep sederhana: Gunakan sesedikit mungkin untuk menyimpan sepotong data."

Bill K
sumber
Bisakah Anda memberikan beberapa referensi? Istilah yang menarik.
Greg Burghardt
13
Pengepakan bit secara teknis benar tetapi juga mengacu pada hal yang lebih umum daripada hanya kondisi boolean - menyimpan data secara umum dalam jumlah bit sekecil mungkin. Sebagai contoh, penggunaan lain dari itu bisa berarti mengompresi chararray dengan meletakkan dua chars menjadi satu int.
Izkata
@GregBurghardt Anda tahu, ini menarik. Saya tidak memikirkannya ketika saya memposting karena istilah itu sangat lazim di tahun 80-an / 90-an ketika saya belajar pemrograman dalam C dan perakitan - sekarang meskipun pencarian google menemukan BANYAK menyebutkan, tidak ada halaman Wikipedia Wikipedia untuk itu . Jawaban pertama di google memiliki definisi ini: "Pengepakan bit adalah konsep sederhana: Gunakan sesedikit mungkin untuk menyimpan sepotong data." kinematicsoup.com/news/2016/9/6/…
Bill K
saat itulah saya belajar tentang pengepakan bit juga, meskipun Anda bisa mendapatkan banyak lebih gila daripada hanya repurposing 0 yang tidak digunakan dalam apa yang secara nominal akan menjadi nilai integer. beberapa tahun yang lalu saya berlari ke sistem yang menyimpan salah satu parameternya sebagai float 8 bit. IIRC 5 bit untuk mantissa yang tidak ditandatangani (semua nilai positif tidak perlu menyimpan tanda secara eksplisit), dan 3 lagi untuk eksponen basis 10. Pada saat itu saya berasumsi itu adalah perangkat keras warisan tanpa jalur maju, tetapi dengan pembelajaran mesin baru-baru ini mulai melakukan hal-hal dengan int4 vs int8, saya bisa melihat beberapa beban kerja menurun dari FP16.
Dan Neely
1
@DanNeely Hal semacam ini juga umumnya didukung oleh GPU - perdagangan antara presisi, memori, dan komputasi cukup penting di sana. Ini telah dieksploitasi dengan cukup baik dengan komputasi berbasis GPU juga.
Luaan
14

Ada banyak istilah berbeda yang digunakan untuk menggambarkan ini.

Paling umum bit disebut "bit flags" atau "bit fields".
(Namun, perlu dicatat bahwa "bidang bit" terkadang merujuk ke fitur spesifik bahasa C dan C ++, yang terkait tetapi tidak persis sama.)

Bilangan bulat itu sendiri disebut sebagai "bit array", "bit set" atau "bit vector", tergantung pada penggunaan dan keadaan.

Either way, mengekstraksi bit dari set bit / vektor / array dilakukan melalui pemindahan dan masking.
(yaitu menggunakan topeng bit .)


Untuk beberapa contoh setiap istilah yang digunakan aktif:


Ini tidak benar-benar berkaitan dengan pertanyaan, tetapi saya ingin mengatakan: tolong jangan gunakan penambahan dan pengurangan untuk mengatur dan menghapus bit karena metode-metode tersebut rentan terhadap kesalahan.
(yaitu jika Anda melakukannya num += 1dua kali, hasilnya setara dengan num += 2.)

Lebih suka menggunakan operasi bitwise yang sesuai, jika bahasa yang Anda pilih menyediakannya:

packStatesIntoNumber ()
{
  let num = 0
  if (this.stateA) num |= 1
  if (this.stateB) num |= 2
  if (this.stateC) num |= 4
  if (this.stateD) num |= 8
  if (this.stateE) num |= 16
  if (this.stateF) num |= 32
  return num
}

unpackStatesFromNumber (num)
{
  this.stateF = ((num & 32) != 0);
  this.stateE = ((num & 16) != 0);
  this.stateD = ((num & 8) != 0);
  this.stateC = ((num & 4) != 0);
  this.stateB = ((num & 2) != 0);
  this.stateA = ((num & 1) != 0);
}
Pharap
sumber
1
this.stateF = (num & 32) ? true : false, dll. Tidak perlu bermutasi numsaat Anda mengekstraksi nilai.
Roger Lipscombe
3
@RogerLipscombe Poin bagus, saya tidak benar-benar membaca apa yang dilakukan kode, hanya bereaksi terhadap penggunaan +dan -. Saya sekarang sudah menggunakan yang lebih baik dan digunakan != 0sebagai pengganti terner, yang saya rasa lebih ringkas sementara masih dieksklusikan.
Pharap