我有一个与大量小整数(实际上是十进制数字)有关的问题。存储此类数据的空间有效方式是什么?
使用std::bitset<4>
存储一个十进制数字是个好主意吗?
答案 0 :(得分:3)
根据 如何节省空间以及检索的效率,我看到了两种可能性:
由于std::bitset<4>
的向量(据我所知)存储在解压缩的设置中(每个位集存储在32或64位的存储器字中),您至少应该使用打包表示,如使用64位字来存储16位数字:
store (if the digit was not stored before):
block |= digit << 4 * index
load:
digit = (block >> 4 * index) & 0xF
reset:
block &= ~(0xF << 4 * index);
这些64位字(uint64_t)的向量以及一些访问方法应该易于实现。
答案 1 :(得分:3)
如果你想要一个非常紧凑的方式,那么不,使用bitset<4>
是一个坏主意,因为bitset<4>
将使用至少一个字节,而不是4位。
我建议使用std::vector<std::uint32_t>
您可以在uint32_t中存储多个数字。两种常用方式:
如果您使用uint64_t
代替uint32_t
,那么您可以使用第一种方式存储16位数字(相同的4位/数字效率),使用第二种方式存储19位数字:3.36bit / digit efficieny ,这非常接近理论最小值:~3.3219bit / digit
答案 2 :(得分:1)
使用std :: bitset&lt; 4&gt;是否是个好主意。存储一个十进制数字?
是的,原则上这是一个好主意。它是众所周知的优化并称为BCD编码。
(实际上是十进制数字)。存储此类数据的空间有效方式是什么?
您可以使用占用字节的一个半字节来压缩十进制数字表示。此外,数学可能会应用于优化,而不是数字等的ASCII表示。
std::bitset<4>
无法为压缩数据提供良好的服务
std::bitset<4>
仍会占据一个完整的字节。
我能想到的另一种数据结构是位域
// Maybe #pragma pack(push(1))
struct TwoBCDDecimalDigits {
uint8_t digit1 : 4;
uint8_t digit2 : 4;
};
// Maybe #pragma pack(pop)
甚至还有一个库可用于将此格式转换为目标CPU架构支持的标准化数字格式:
我能想到的另一种方法是编写自己的类:
class BCDEncodedNumber {
enum class Sign_t : char {
plus = '+' ,
minus = '-'
};
std::vector<uint8_t> doubleDigitsArray;
public:
BCDEncodedNumber() = default;
BCDEncodedNumber(int num) {
AddDigits(num); // Implements math operation + against the
// current BCD representation stored in
// doubleDigitsArray.
}
};