Birçok boolean durumu tek bir numaraya depolamak / paketlemek için kullanılan ad nedir?


55

Bu, iki boolean / binary durumunu saklamak için bir sayısal değişkeni kullandığınız, iki katlamayı ve iki kat sayıların önceki sayıların toplamının 1 + olduğu gerçeğini kullanan basit bir sıkıştırma türüdür.

Eski, iyi bilinen bir teknik olması gerektiğine eminim, doğru bir şekilde neyi kastedildiğini bilmek istiyorum. Tarif etmeyi düşündüğüm her yolla ilgili birçok araştırma yaptım, ancak makale yazarlarının bunu kendilerinin çözdüğü ve ne diyeceğini bilemedikleri bazı blog makalelerinin ötesinde hiçbir şey bulamadım ( örnek 1 , örnek 2 ).

Örneğin, işte kavramı göstermek için çok basit bir uygulama:

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
}

Ayrıca bitsel operatörleri, baz 2 sayı ayrıştırma, numaralandırmaları kullanabilirsiniz. Uygulamanın daha verimli yolları var, daha genel olarak yaklaşımın adıyla ilgileniyorum.


8
C #, vardır enumsve bir Flagsöznitelik olabilir. Kodunuzu çok daha kolay hale getirebilirler.
Bernhard Hiller

12
Buna "taklit bit alanları" derdim. Alan verimliliği çok önemli olmadığı sürece, neredeyse her zaman kötü bir fikirdir.
Kilian Foth

7
@KilianFoth A boolgenellikle dahili olarak 32 bit tam sayı olarak saklanır. Bu nedenle, paketleme 32 faktörünün farkını yaratabilir. Bu gerçekten çok fazla. Demek istediğim, biz programcılar kaynaklarımızın yarısını atmaya her zaman hazırız, ancak genellikle bunların% 97'sini atmak konusunda isteksizim. Bu tür atık faktörleri, önemli kullanım durumlarını çalıştırabilmek ve hafızasının tükenmesi arasında kolayca fark yaratabilir.
cmaster

3
Tarihsel olarak, tipik olarak bit maskelerinin değerleri bildirmek, ayarlamak ve almak için kullanılır. Vardiya kullanılması gariptir ve yaklaşımın en iyi örneği değildir.
JimmyJames,

3
@cmaster Sebeplerin bu şekilde depolanmasının nedeni, tek bir hafıza konumunu (günümüz makinelerinde 32 veya 64 bit) paylaşmak, makine dili koduna çok fazla dikkat etmediğiniz sürece önbellek performansı için çok kötü olabileceğidir. Gerçekten çok sayıda bitiniz varsa, buna değer, ancak buna değer, ancak muhtemelen daha iyi durumda değilseniz önceden optimize etmemeniz ve ağa veya diske aktarmaya hazır olduğunuzda bitleri paketlemeniz daha iyi olmaz.
Bill K,

Yanıtlar:


107

En yaygın olarak bit alanı olarak adlandırılır ve sık sık duyacağınız bir başka terim , tek tek bit değerlerini veya tüm bit alanını aynı anda almak veya ayarlamak için kullanılan bit maskeleridir .

Pek çok programlama dili, bu konuda yardımcı olacak yardımcı yapılara sahiptir. @BernhardHiller yorumlarda da belirtildiği gibi, C # bayraklarıyla numaralandırır ; Java, EnumSet sınıfına sahiptir.


4
"Bit alanı" nı tek tek bitlerin bitsel operatörlerle elle yapmak yerine bir yapının alanlarına atanmasına izin veren bir dil özelliği olarak yorumlardım.
Peter Green

22
@PeterGreen Bu standart yorumdan farklı olurdu.
Eric

1
"Bit Eşleme" veya "Bit Eşleme", kayıt kümeleri ve dizi işleme için ortak iken, bu durumda da geçerli olabilir. Ortak elemanları çoklu kümelerden çıkarırken, bir federasyon modelin bileşenlerini tanımlamak için değer ayrıştırılabilir. Sekizli filemode rakamları bile söylüyoruz. Bit Maskeleri (herhangi bir maske) filtre olma eğilimindedir (IO portları ve veri yönü kayıtları için olduğu gibi).
mckenzm

1
C # ayrıca, BitArraykeyfi bir miktarda bitin depolanmasına ve endekslenmesine izin verir (bayraklar bir tamsayı türüyle sınırlı ve maske olarak kullanılması amaçlanmıştır).
Luaan

Doğru; Az önce aşina olduğum iki yapıdan bahsettim. Özellikle diğer dillerde, muhtemelen onlarca orada var.
Glorfindel

20

Garip, burada biraz farklı terimler var ama hemen aklıma gelen bir terim göremiyorum (ve sorunuzun başlığında!) - Bit Ambalaj her zaman ne dediğini duyduğum şey.

Bunun gerçekten bariz olduğunu düşünmüştüm, ama garip bir şekilde google'da bu, yaygın olarak kullanılan ancak resmi olarak tanımlanmayan bir terim gibi görünüyor (Wikipedia, biraz paketlemenin bir yolu olan bit alanına yönlendiriyor gibi görünüyor. işlemi). Tanımın aranması bu sayfaya yol açıyor gibi görünüyor:

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

SO amaçları için harika değil ama bu özlü açıklamayı da dahil ederek bulabileceğim en iyi tanım / açıklama: "Bit paketleme basit bir kavramdır: Bir veri parçasını saklamak için mümkün olduğunca az bit kullanın."


Bazı referanslar verebilir misiniz? İlginç terim
Greg Burghardt

13
Bit paketlemesi teknik olarak doğrudur ancak aynı zamanda sadece boolean durumlardan daha genel olanı ifade eder - verileri genel olarak mümkün olan en az bit sayısına depolar. Örneğin, bir başka kullanım, bir chardiziyi iki chars'yi bir içine koyarak sıkıştırmak anlamına gelebilir int.
Izkata

@GregBurghardt Biliyorsunuz, ilginç. C ve meclis programlarını öğrendiğimde terim 80’lerin / 90’larda oldukça yaygın olduğu için bunun hakkında düşünmedim - bir google araması MANY’nin dediği gibi kesin bir Wikipedia sayfası bulunmamasına rağmen . Google’daki ilk cevap şu tanımlara sahiptir: "Bit paketleme basit bir kavramdır: Bir veri parçasını saklamak için mümkün olduğunca az bit kullanın." kinematicsoup.com/news/2016/9/6/…
Bill K

o zaman ben de bit paketlemeyi öğrendiğimde, kullanılmayan 0'ları nominal olarak tamsayı değerlerinde olacak şekilde yeniden yerleştirmekten çok daha çılgınca olabiliyor olsanız da. Birkaç yıl önce, parametrelerinden birini 8 bitlik bir yüzer olarak depolayan bir sisteme rastladım. Bir imzasız mantis için IIRC 5 bit (tüm değerler işaretini açıkça saklamaya gerek kalmadan pozitifti) ve 10 üs üs için 3 tane daha. İleriye dönük yolu olmayan eski bir donanım çamuru olduğunu farz ettim, ancak son zamanlarda makine öğrenimi int4 vs int8 ile bir şeyler yapmaya başladıysa, FP16'dan bazı iş yüklerinin azaldığını görebiliyordum.
Dan Neely

1
@DanNeely Bu tür şeyler genellikle GPU'lar tarafından da desteklenir - hassasiyet, bellek ve hesaplama arasında ticaret yapmak oldukça önemlidir. Bu GPU tabanlı bilgi işlem ile de oldukça iyi bir şekilde kullanıldı.
Luaan

14

Bunu tarif etmek için kullanılan birçok farklı terimler vardır.

En yaygın olarak bitlere "bit bayrakları" veya "bit alanları" denir.
(Bununla birlikte, "bit alanları" nın bazen C ve C ++ dillerinin belirli bir özelliğine atıfta bulunduğunu, bununla ilişkili ancak tam olarak aynı olmadığını belirtmekte fayda vardır.)

Tamsayının kendisi, kullanım ve koşullara bağlı olarak, çeşitli şekillerde "bit dizisi", "bit kümesi" veya "bit vektörü" olarak adlandırılır.

Her iki durumda da, bit set / vector / array'den bitlerin çıkarılması, kaydırma ve maskeleme ile yapılır.
(yani bir bit maskesi kullanarak )


Aktif kullanımdaki her bir terimin bazı örnekleri için:


Bu soruya gerçekten uygun değil ama şunu söylemek isterim: lütfen bu yöntemler hataya açık olduğundan bitleri ayarlamak ve silmek için toplama ve çıkarma kullanmayın.
(yani num += 1iki kez yaparsanız , sonuç eşittir num += 2.)

Seçtiğiniz dil bunları sağlarsa, bunun yerine uygun bitwise işlemleri kullanmayı tercih edin:

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);
}

1
this.stateF = (num & 32) ? true : false, vb numDeğerleri çıkarırken mutasyona gerek yok .
Roger Lipscombe

3
Gerçekten sadece kullanımına tepki, kod ne yaptığını okuduktan değildi, iyi noktayı @RogerLipscombe +ve -. Şimdi daha iyi oldum ve != 0üçlü yerine kullandım , ki hala patlarken daha özlü hissediyorum.
Pharap
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.