在处理Project Euler问题时,我经常需要大型(> 10 ** 7)位数组。
我的常规方法之一是:
bool* sieve = new bool[N];
bool sieve[N];
当N = 1,000,000时,我的程序使用1兆字节(8 * 1,000,000位)。
在c ++中使用存储位数组是否比bool更有效?
答案 0 :(得分:21)
使用std::bitset
(如果N
是常量),否则请使用其他人提及的std::vector<bool>
(但不要忘记阅读Herb Sutter的this excellent article)
bitset是一个特殊的容器类,用于存储位(只有两个可能值的元素:0或1,true或false,......)。
该类非常类似于常规数组,但优化空间分配:每个元素只占一位(比C ++中最小的元素类型小八倍:char)。 / p>
修改强>:
Herb Sutter(在那篇文章中)提到
std :: vector&lt;的原因bool&gt;是不合格的是它为了优化空间而在幕后挖掘技巧:而不是为每个bool [1]存储一个完整的char或int(占用空间的至少8倍,在具有8位字符的平台上) ,它打包bools并将它们作为单独的位(内部,比如,字符)存储在其内部表示中。
std :: vector&lt; bool&gt;通过将其纳入标准,强制对所有用户进行特定优化。这不是一个好主意;不同的用户有不同的要求,现在所有向量用户都必须支付性能损失,即使他们不想要或不需要节省空间。
编辑2 :
如果您使用过Boost,则可以使用boost::dynamic_bitset
(如果在运行时已知N
)
答案 1 :(得分:12)
为了更好或更坏,std::vector<bool>
将使用位而不是bool,以节省空间。所以,只需使用std::vector
,就像你应该在第一时间一样。
如果N
是常量,则可以使用std::bitset
。
答案 2 :(得分:4)
您可以查看std::bitset
和std::vector<bool>
。后者通常被推荐反对,因为尽管名称中有vector
,但它实际上并不像任何其他类型的对象的向量,并且实际上不满足一般容器的要求。尽管如此,它可能非常有用。
答案 3 :(得分:4)
仅使用1位不存储'bool'类型。根据你对大小的评论,似乎每个bool使用1个整个字节。
C这样做的方法是:
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是表示字节的十六进制数。
答案 4 :(得分:3)
是的,您可以使用bitset。
答案 5 :(得分:2)
您可能有兴趣尝试使用BITSCAN库。最近有一个扩展已被提议用于稀疏性,我不确定是你的情况,但可能是。
答案 6 :(得分:0)
答案 7 :(得分:0)
您可以使用字节数组和索引。索引n
将位于字节索引n/8
中,位#n%8
。 (如果由于某种原因std :: bitset不可用)。
答案 8 :(得分:0)
如果在编译时知道N,请使用std::bitset,否则使用boost::dynamic_bitset。
答案 9 :(得分:0)
A&#39; bool&#39;类型不仅仅使用1位存储。根据你对大小的评论,似乎每个bool使用1个整个字节。
C这样做的方法是:
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);