繁体   English   中英

如何在C ++中构建N位变量?

[英]How to build N bits variables in C++?

我正在处理C ++中非常大的布尔列表,每个约有2 ^ N个N布尔值。 因为内存在这种情况下是关键的,即指数增长,我想构建一个N位长变量来存储每个元素。

对于小N,例如24,我只使用unsigned long int 需要64MB((2 ^ 24)* 32/8/1024/1024)。 但是我需要达到36.内置变量的唯一选择是unsigned long long int ,但它需要512GB((2 ^ 36)* 64/8/1024/1024/1024),这也有点许多。 使用36位变量,它可以为我工作,因为大小下降到288GB((2 ^ 36)* 36/8/1024/1024/1024),这适合我的超级计算机的节点。

我尝试了std::bitset ,但是std::bitset< N >创建了一个至少为8B的元素。 因此, std::bitset< 1 >的列表远大于unsigned long int的列表。 这是因为std::bitset只是改变了表示,而不是容器。

我也尝试过来自Boost的boost::dynamic_bitset<> ,但结果甚至最差(至少32B!),出于同样的原因。

我知道一个选项是将所有元素写为一个布尔链,2473901162496(2 ^ 36 * 36),然后存储在38654705664(2473901162496/64) unsigned long long int ,它给出288GB(38654705664 * 64/8 / 1024/1024/1024)。 然后访问元素只是找到存储36位的元素的游戏(可以是一个或两个)。 但是现有代码(3000行)的重写很多,因为映射变得不可能,并且因为在某些功能执行期间添加和删除项目肯定会复杂,混乱,具有挑战性,结果很可能效率不高。

如何在C ++中构建一个N位变量?

一个有5个字符的结构怎么样(可能需要一些花哨的运算符重载来保持它与现有代码兼容)? 由于填充/对齐,具有long和char的结构可能不起作用...

基本上你自己的迷你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));
     }
   }
};

编辑 :正如geza在他评论中指出的那样,这里的“技巧”是尽可能接近所需的最小字节数(不通过触发对齐丢失,填充或指针间接来浪费内存,请参阅http:// www.catb.org/esr/structure-packing/ )。

编辑2 :如果你觉得有冒险精神,你也可以尝试一下这个领域(请告诉我们它实际消耗的空间):

struct Bitset36 {
  unsigned long long data:36;
}

我不是专家,但我会“尝试”。 找到编译器支持的最小类型的字节(应该是char)。 您可以检查sizeof,你应该得到1.这意味着1个字节,所以8位。

所以如果你想要一个24位类型......你需要3个字符。 对于36你需要5个char数组,你最后会有4位浪费的填充。 这很容易解释。

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

现在制作一个掩码来访问typeSize的每个位置。

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;

现在您可以按位使用或在需要的地方将值设置为1。

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

要关闭位,请使用&运算符..

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

您可以使用&运算符读取每个位的位置。

typeSize[0] & four

请记住,我没有编译器方便尝试这个,所以希望这是一个有用的方法来解决你的问题。

祝好运 ;-)

您可以使用unsigned long int数组,并使用按位运算存储和检索所需的位链。 这种方法排除了空间开销。

无符号字节数组B []和12位变量V(表示为ushort)的简化示例:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM