非整数2个整数的包装集

时间:2018-05-22 14:11:52

标签: algorithm integer compression bit-manipulation

我有一组整数,每个整数都有一个特定的范围:

foo = [1, 5]
bar = [1, 10]
baz = [1, 200]

我可以根据它们可以拥有的不同状态的数量来计算分别存储每个数字需要多少位:

foo = 5 possible states   ~ 3 bits
bar = 10 possible states  ~ 4 bits
baz = 200 possible states ~ 8 bits

这总共给了我15位。但是每个数字都有一个未使用的范围,导致空间浪费。我可以通过计算所有组合数的所有可能状态来计算整个集合的所需位:

5 * 10 * 200 = 10000 possible states ~ 14 bits

这可以节省我一点!

这就是我的问题所在:使用这种类型的布局加载和存储数字的最佳方法是什么?

1 个答案:

答案 0 :(得分:4)

具有不同范围的变量列表,如下所示:

foo = [1, 5]
bar = [1, 10]
baz = [1, 200]

可以(几乎?)被解释为混合基数表示。如果它们从零开始,则对应关系将是立即的,但是因为它们从一开始(或者一般来说:如果它们是任何有限的可能性集合),它们必须首先重新映射,这里只需减去一个转换为"打包"状态并在再次解码时添加一个。

编码很简单,只涉及廉价操作:

packed = (foo - 1) + 5 * (bar - 1) + (5 * 10) * (baz - 1)

比例因子当然来自可能的状态数。每个元素都需要重新映射到从零开始的连续范围,然后按前面元素的#states的乘积缩放,第一个元素按1缩放(空产品)。顺便说一下,[1 .. 5]有5个状态,而不是4个。

解码涉及剩余部分和分部,最简单(但通常不是最快)的方法是逐位提取:

// extract foo
foo = packed % 5 + 1
// drop foo from packed representation
packed /= 5
// extract bar (which is now the lowest digit in 'packed')
bar = packed % 10 + 1
// drop bar
packed /= 10
// top digit is left over
baz = packed + 1

对于更大的例子,首先" chop"将打包的数字分成几个独立的部分,然后独立解码。这可以防止产生长链的相关操作,这种操作自然会导致数字逐字方法。

直接使用压缩表示通常很棘手,除了要添加和减去元素,如果你知道它不会溢出。