2017-10-31 117 views
6

C++ 'da çok fazla boole listesiyle uğraşıyorum, her biri yaklaşık 2^N N booleans ürün. Bellek, bu durumda, yani üstel bir büyüme açısından kritik olduğu için, her bir öğeyi depolamak için bir N-bit uzun değişkeni oluşturmak isterim.C++'da N bit değişkenleri nasıl oluşturulur?

Küçük N için, örneğin 24, sadece unsigned long int kullanıyorum. 64MB ((2^24) * 32/8/1024/1024) alır. Fakat 36'ya kadar çıkmam gerekiyor. Yapılandırma değişkenine sahip tek seçenek unsigned long long int'dur, ancak 512GB ((2^36) * 64/8/1024/1024/1024) alır, bu da biraz fazladır. 36 bitlik bir değişkenle, benim için çalışacaktır çünkü boyut, süper bilgisayarımın bir düğümündeki 288 GB ((2^36) * 36/8/1024/1024/1024) değerine düşer.

std::bitset'u denedim, ancak std::bitset<N> en az 8B'lik bir öğe oluşturur. std::bitset<1>'un bir listesi, unsigned long int listesinden çok daha büyüktür. Bunun nedeni, std::bitset'un yalnızca kapsayıcı değil, gösterimi değiştirmesidir.

Ayrıca Boost'dan boost::dynamic_bitset<>'u denedim, ancak aynı nedenden dolayı sonuç en kötüsüdür (en az 32B!).

Bir seçenek daha sonra (38654705664 * 64/8 288GB verir 38654705664 (2473901162496/64) unsigned long long int, daha sonra kaydetmek için, Boolean bir zincir, 2473901162496 (* 36 2^36) tüm elemanları yazma olduğunu biliyoruz/1024/1024/1024). Daha sonra bir öğeye erişmek için, 36 bitin hangi öğelerde saklandığını bulmak mümkündür (bir veya iki olabilir). Ancak, mevcut kodun (3000 satır) yeniden yazılması çok fazladır çünkü haritalama imkansız hale gelir ve bazı işlevlerde yürütme sırasında öğelerin eklenmesi ve silinmesi kesinlikle karmaşık, karmaşık ve zorlayıcı olacaktır ve sonuç büyük olasılıkla verimli olmayacaktır.

C++'da N-bit değişkeni nasıl oluşturulur?

+3

? Çok miktarda bit depolamanız gerekiyorsa iyi bir seçimdir. – VTT

+0

Bir "std :: array " veya "std :: vector " boyutunun sadece number_of_bits_needed/sizeof (uint8_t) boyutu nasıl kullanılır? –

+0

"İmzasız uzun uzun" dizisinden ziyade, neden tek bir "dynamic_bitset" değil? Daha sonra X elemanının bulunması, N * X bitlerinin içine girmesi kadar basit hale gelir. Bu, onu kullanmanın mantığını sadeleştirir (ve bununla ilgili olarak özetleyebilirsiniz). Eksik olan ana şey, arkada olmayan ekleme/silme işlemidir. – chris

cevap

5

5 karakterli bir yapıya (ve belki de varolan koda uyumlu olmasını sağlamak için gerektiğinde aşırı yüklenme yapan bazı fantezi operatörler) ne dersiniz? Uzun ve bir karakter muhtemelen dolgu/uyum çalışmaz ile yapı ...

Temelde kendi mini boyutu için optimize bitset:

struct Bitset40 { 
    unsigned char data[5]; 
    bool getBit(int index) { 
    return (data[index/8] & (1 << (index % 8))) != 0; 
    } 
    bool setBit(int index, bool newVal) { 
    if (newVal) { 
     data[index/8] |= (1 << (index % 8)); 
    } else { 
     data[index/8] &= ~(1 << (index % 8)); 
    } 
    } 
}; 

Düzenleme: Geza da işaret ettiği gibi int yorum olarak, "hile" burada, gerekli minimum bayt sayısına (hizalama kayıplarını, doldurma veya işaretçi indirgemeyi tetikleyerek bellek israf etmeden, http://www.catb.org/esr/structure-packing/'a bakın) mümkün olduğunca yakınlaşmaktır.

Düzenleme 2: Maceracı düşünüyorsanız, aynı zamanda biraz alanını denemek (ve bize aslında tüketir ne kadar boşluk bildirin lütfen) olabilir:

struct Bitset36 { 
    unsigned long long data:36; 
} 
+0

Harika! Bu, geza'nın yorumunu gördükten sonra yazdığım şey. Maalesef, "sizeof (Bitset36)" 8B'dir. –

+0

Son düzenleme, yerel bit alanlarının anlaşılmaması ve test olmaması anlamına geldiğinden, buna dahil edilmeye değer değildir. Yerel bitset'ler, birden çok bitişik alanı, paylaşılan türlerine "sizeof" olarak yerleştirmenize izin verir; Onlar bunu indiremezler. –

+0

@underscore_d Anlayışım için, bit alanlarının tüm depolama ve bellek özellikleri, uygulama tanımlıdır. Bu yüzden yerel olarak test yapmak gerekli bir yardım gerektirmiyordu ve buradaki şartlar, kullanım durumunu basitleştiren 40 bitlik bir düşüşü engelliyor. Birden çok bitişik alanın boyutlarının farklı olabileceğinden, "ortak türlerinin büyüklüğü" ile tam olarak ne kastettiğinizden emin değilsiniz. –

1

Sen unsigned long int ve mağazanın dizi kullanabilirsiniz ve bitsel işlemlerle gerekli bit zincirlerini alın. Bu yaklaşım boşluk ekini içermez. (USHORT olarak ifade edilir), işaretsiz bayt dizisi B [] ve 12 bit değişken V

basitleştirilmiş örnek:

Set V[0]: 
B[0] = V & 0xFF; //low byte 
B[1] = B[1] & 0xF0; // clear low nibble 
B[1] = B[1] | (V >> 8); //fill low nibble of the second byte with the highest nibble of V 
3

Ben bir uzman, ama bu, "deneyin" budur. Derleyicinizin desteklediği en küçük tür için baytları bulun (char olmalıdır). Sizeof ile kontrol edebilirsiniz ve 1 almalısınız. Bu, 1 bayt, yani 8 bit anlamına gelir.

Eğer 24 bitlik bir yazı tipi istiyorsanız 3 karaktere ihtiyacınız olacak. 36 için 5 karakter dizisine ihtiyacınız olacak ve sonunda 4 bit israf dolusu dolgusu olacaktı. Bu kolayca hesaba katılabilir. yani

char typeSize[3] = {0}; // should hold 24 bits 

Şimdi puntolarla her pozisyonunu erişmek için biraz maske yapın.

const unsigned char one = 0b0000'0001; 
const unsigned char two = 0b0000'0010; 
const unsigned char three = 0b0000'0100; 
const unsigned char four = 0b0000'1000; 
const unsigned char five = 0b0001'0000; 
const unsigned char six = 0b0010'0000; 
const unsigned char seven = 0b0100'0000; 
const unsigned char eight = 0b1000'0000; 

Artık bit temelinde

typeSize[1] |= four; 
*typeSize[0] |= (four | five); 

bit & operatörünü kullanmak kapatmak için .. ya da ihtiyaç 1'e değerleri ayarlamak için ..

typeSize[0] &= ~four; 
typeSize[2] &= ~(four| five); 

kullanabilirsiniz Her bitin konumunu & operatörüyle okuyabilirsiniz.

typeSize[0] & four 

Ayı akılda, bu denemek için kullanışlı bir derleyici zorunda kalmamak için umarım bu sorununuza yararlı bir yaklaşımdır.

iyi şanslar ;-) Nasıl `:: std :: vector ` yaklaşık

+0

Stefan Haustein'dan daha benzer cevap, bu hile yapacak! –

+0

Cevabınız ayrıca soruma cevap veriyor, ancak iki yanıtı "kabul edemiyorum". –

+0

Eğer birisi sizeof (char) 'ı kontrol ederse ve' 1' almazsa, tamamen eşit bir derleyiciye sahip olurlar, çünkü bu eşitlik dilin temel bir ilkesidir. –

İlgili konular