在缓冲区中打包3个值的数组

时间:2015-03-11 22:20:12

标签: c++ c memory bit-manipulation information-theory

我有以下问题,我无法优雅地解决。

我的数据类型可以包含3个可能的值(0,1,2)。 我有一个包含此数据类型的20个元素的数组。

由于我想对最少量内存的信息进行编码,我做了以下内容:

  • 考虑每个元素最多可以占用4个值(2位)
  • 每个char保存8位,所以我可以放4次元素
  • 5 char持有40位,因此我可以存储20个元素。

我做到了这一点并且有时间。

然而,我感兴趣的是通过使用我的元素只能获取3个值而不是4个值的事实来评估所获得的空间。 每种可能的组合给我们3到20次幂,即3,486,784,401。然而,256到4的功率给了我们4,294,967,296,这是更大的。这意味着我可以在4 char上编码我的数据。

这里有第二种想法的通用方法吗?第一个想法很容易实现位掩码/位移。但是由于3个值不适合整数位,我不知道如何将这些值中的任何值编码/解码为4个字符的数组。

您对它是如何完成有任何想法或参考吗?我认为必须有一般方法。如果有什么我对这个可行性感兴趣

编辑:这可以简化为:如何将0到2的5个值仅存储为1个字节(256> = 3 ^ 5 = 243)

2 个答案:

答案 0 :(得分:5)

你应该能够用4个字节做你说的话。假设您将20个值存储到一个名为int32_t的{​​{1}}中,以下是提取任何特定元素的方法:

value

或作为循环:

element[0] = value % 3;
element[1] = (value / 3) % 3;
element[2] = (value / 9) % 3;
...
element[19] = (value / 1162261467) % 3; // 1162261467 = 3 ^ 19

要从for (i=0;i<20;i++) { element[i] = value % 3; value /= 3; } 构建value,您只需执行相反操作,如下所示:

element

答案 1 :(得分:0)

有一种通用的方法可以计算出你需要多少比特:

如果您的数据类型具有 N 不同的值,则需要 log(N)/ log(2)位来存储此值。例如,在您的示例中, log(3)/ log(2)等于1.585位。

当然,实际上你将以整数位包装一个固定数量的值,所以你必须将这个1.585乘以该数量并向上舍入。例如,如果你打包其中5个:

1.585×5 = 7.925 ,这意味着您的5个值只适合一个8位char

解压缩值的方法已在JS1的答案中显示。解包的通用公式是 element [i] =(value /(N ^ i))mod N

最后请注意,这只有在您真正需要优化内存使用情况时才有意义。为了比较,以下是人们打包这些价值类型的一些流行方式。大多数情况下,占用的额外空间不是问题。

  • bool的数组:使用8位来存储一个bool。许多人真的不喜欢std::vector<bool>的行为。
  • enum Bla { BLA_A, BLA_B, BLA_C}; Bla的数组或向量可能每个元素使用32位(sizeof(Bla) == sizeof(int))。