[英]Bit Array in C++
在使用Project Euler問題時,我經常需要大型(> 10 ** 7)位數組。
我的正常方法是:
bool* sieve = new bool[N];
bool sieve[N];
當N = 1,000,000時,我的程序使用1兆字節(8 * 1,000,000位)。
在c ++中使用存儲位數組是否比bool更有效?
使用std::bitset
(如果N
是常量),否則使用std::vector<bool>
就像其他人提到的那樣(但不要忘記閱讀Herb Sutter的這篇優秀文章 )
bitset是一個特殊的容器類,用於存儲位(只有兩個可能值的元素:0或1,true或false,......)。
該類與常規數組非常相似, 但優化空間分配 :每個元素只占一位(比C ++中最小的元素類型小八倍:char)。
編輯 :
Herb Sutter(在那篇文章中)提到了這一點
std :: vector <bool>不合格的原因是它為了優化空間而在底層提取技巧:而不是為每個bool [1]存儲一個完整的char或int(占用至少8倍的空間) ,在具有8位字符的平台上), 它打包bool並將它們作為單獨的位 (內部,比如,字符)存儲在其內部表示中。
std :: vector <bool>通過將其包含在標准中來強制對所有用戶進行特定優化。 這不是一個好主意; 不同的用戶有不同的要求,現在所有向量用戶都必須支付性能損失,即使他們不想要或不需要節省空間。
編輯2 :
如果你使用過Boost,你可以使用boost::dynamic_bitset
(如果N
在運行時已知)
無論好壞, std::vector<bool>
將使用位而不是bool,以節省空間。 所以只需使用std::vector
就像你應該在第一時間一樣。
如果N
是常量 ,則可以使用std::bitset
。
你可以查找std::bitset
和std::vector<bool>
。 后者通常被推薦反對,因為盡管名稱中的vector
,它實際上並不像任何其他類型的對象的矢量,並且實際上不滿足一般容器的要求。 盡管如此,它可能非常有用。
OTOH,沒有任何東西(至少可靠地)以不到100萬比特存儲100萬個bool值。 它根本無法確定。 如果你的位集包含一定程度的冗余,那么有各種壓縮方案可能是有效的(例如,LZ *,霍夫曼,算術),但是如果不了解內容,就不可能說它們是肯定的。 但是,這些中的任何一個通常都會將每個bool / bit存儲在一個存儲位中(加上一點點用於簿記的開銷 - 但這通常是一個常量,並且最多為字節到幾十個字節)。
僅使用1位不存儲'bool'類型。 根據你對大小的評論,似乎每個bool使用1個整個字節。
AC喜歡這樣做的方式是:
uint8_t sieve[N/8]; //array of N/8 bytes
然后邏輯OR字節一起得到你所有的位:
sieve[0] = 0x01 | 0x02; //this would turn on the first two bits
在該示例中,0x01和0x02是表示字節的十六進制數字。
是的,你可以使用bitset 。
您可能有興趣嘗試BITSCAN庫作為替代方案。 最近有一個擴展已被提議用於稀疏性,我不確定是你的情況,但可能是。
您可以使用字節數組和索引。 索引n
將在字節索引n/8
,位# n%8
。 (如果由於某種原因std :: bitset不可用)。
如果在編譯時已知N,則使用std :: bitset ,否則使用boost :: dynamic_bitset 。
僅使用1位不存儲'bool'類型。 根據你對大小的評論,似乎每個bool使用1個整個字節。
AC喜歡這樣做的方式是:
uint8_t sieve[N/8]; //array of N/8 bytes
數組的元素是:
result = sieve[index / 8] || (1 << (index % 8));
要么
result = sieve[index >> 3] || (1 << (index & 7));
在數組中設置1:
sieve[index >> 3] |= 1 << (index & 7);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.