将两个或多个数字压缩为一个字节

时间:2010-08-17 04:57:00

标签: algorithm math

我认为这不太可能,但无论如何都值得一提。假设我有两个小数字(每个范围从0到11)。是否一种方式我可以将它们压缩成一个字节并稍后将它们取回。有四个相似大小的数字怎么样。

我需要的是:a1 + a2 = x。我只知道x并从中得到a1,a2
对于第二部分:a1 + a2 + a3 + a4 = x。我只知道x并从中得到a1,a2,a3,a4
注意:我知道你无法解决,只是说明我的问题。

x必须是一个字节。 a1,a2,a3,a4范围[0,11]。

11 个答案:

答案 0 :(得分:12)

这有点掩码的微不足道。想法是将字节划分为更小的单元并将它们分配给不同的元素。

对于2个数字,它可以是这样的:前4位是number1,其余是number2。您可以使用number1 = (x & 0b11110000) >> 4number2 = (x & 0b00001111)来检索值,并使用x = (number1 << 4) | number2来压缩它们。

答案 1 :(得分:9)

对于两个数字,当然。每个都有12个可能的值,因此该对总共有12 ^ 2 = 144个可能的值,并且小于一个字节的256个可能值。所以你可以这样做。

x = 12*a1 + a2
a1 = x / 12
a2 = x % 12

(如果你只有签名字节,例如在Java中,它有点棘手)

对于0到11之间的四个数字,有12 ^ 4 = 20736个值,所以你不能将它们放在一个字节中,但你可以用两个来完成。

x = 12^3*a1 + 12^2*a2 + 12*a3 + a4
a1 = x / 12^3
a2 = (x / 12^2) % 12
a3 = (x / 12) % 12
a4 = x % 12

编辑:其他答案谈论每四位存储一个数字并使用位移。那更快。

答案 2 :(得分:2)

0-11示例非常简单 - 您可以将每个数字存储为四位,因此将它们放入一个字节只需将一个4位向左移位,or两个在一起。

四个相似大小的数字将不适合 - 每四位四位至少四位至少保留16位。

答案 3 :(得分:1)

如果数字0-11不均匀分布,则可以通过对较常用的值使用较短的位序列,对较稀有的值使用较长的位序列,可以做得更好。编码你使用的长度至少要花费一个代码,所以CS的整个分支用于证明它何时值得做。

答案 4 :(得分:1)

让我们说一般:假设你要混合N个数字a1,a2,... aN,a1范围从0..k1-1,a2从0..k2-1,...和aN来自0 .. kN-1。

然后,编码的数字是:

encoded = a1 + k1*a2 + k1*k2*a3 + ... k1*k2*..*k(N-1)*aN

然后解码更加棘手:

rest = encoded
a1 = rest mod k1
rest = rest div k1

a2 = rest mod k2
rest = rest div k2

...

a(N-1) = rest mod k(N-1)
rest = rest div k(N-1)

aN = rest # rest is already < kN

答案 5 :(得分:0)

因此一个字节最多可以容纳256个值或十六进制的FF。因此,您可以在一个字节中编码0-16中的两个数字。

byte a1 = 0xf;
byte a2 = 0x9;
byte compress = a1 << 4 | (0x0F & a2);  // should yield 0xf9 in one byte.

如果将其减少到0-8范围,则可以执行4个数字。

答案 6 :(得分:0)

由于单个字节是8位,因此您可以使用较小的值范围轻松细分它。这种情况的极限是当你有8个单位整数时,称为位字段。

如果你想存储两个4位整数(每个整数为0-15),你只需要这样做:

value = a * 16 + b;

只要你进行适当的边界检查,你就不会丢失任何信息。

要获得这两个值,您只需要这样做:

a = floor(value / 16)
b = value MOD 15

MOD是模数,它是除法的“余数”。

如果要存储四个2位整数(0-3),可以执行以下操作:

value = a * 64 + b * 16 + c * 4 + d

然后,让他们回来:

a = floor(value / 64)
b = floor(value / 16) MOD 4
c = floor(value / 4) MOD 4
d = value MOD 4

我将最后一个师作为练习留给读者;)

答案 7 :(得分:0)

@Mike Caron

你的最后一个例子(0-3之间的4个整数)比特移位要快得多。不需要楼层()。

value = (a << 6) | (b << 4) | (c << 2) | d;

a = (value >> 6);
b = (value >> 4) % 4;
c = (value >> 2) % 4;
d = (value) % 4;

答案 8 :(得分:0)

使用位屏蔽或位移。后者更快

测试BinaryTrees以获得一些乐趣。 (它将在以后的开发生活中处理有关数据和各种各样的dev voodom lol)

答案 9 :(得分:0)

将四个值打包成一个数字至少需要15位。这不适合单个字节,但只有两个。

您需要做的是从基数12转换为基数65536,反之亦然。

B = A1 + 12.(A2 + 12.(A3 + 12.A4))

A1 = B % 12
A2 = (B / 12) % 12
A3 = (B / 144) % 12
A4 = B / 1728

因为这需要2个字节,所以从基数12到(打包)基数16的转换是可以预先设定的。

B1 = A1 + 256.A2
B2 = A3 + 256.A4

A1 = B1 % 256
A2 = B1 / 256
A3 = B2 % 256
A4 = B2 / 256

模数和分歧是通过掩码和转换来实现的。

答案 10 :(得分:0)

0-9更容易。您可以轻松地以4 1/2字节存储11个随机顺序小数。哪个是比log(256)÷log(10)更紧密的压缩。只是通过创意映射。请记住,并非所有压缩都与字典,冗余或序列有关。

如果你在谈论随机数0 - 9,你可以每14位而不是15位有4位数。