自定义数据类型压缩

时间:2013-09-23 14:29:41

标签: compression

我目前有一个应用程序要求我以尽可能少的位发送数据。例如,如果我以度数给出方向,则范围为0-359。这意味着9位,我有一个数字0 - 511,分辨率为1.会有152个可能的结果“浪费”。我可以将这些可能的结果用于错误处理,但我想知道是否有任何方法可用于打包更多数据。

我唯一的另一个想法是我可以添加359/511的乘法因子,这样我就可以更精确地进行挤压。

编辑:其他信息:

  1. 应该假设并非所有消息都能通过
  2. 一些字段示例:

    方向基(360) 日基(366) 小时基数(24) 分钟基数(60)

    通过这三个例子,总浪费的结果是905。

2 个答案:

答案 0 :(得分:2)

对于一个数字,你显然不能少于9位,所以你不能做得更好。但对于多个数字,你可以做得更好。我想到了两件事:

您可以在基本360中一次传输多个数字。以下是编码和三个数字的方法:

int encoded = num0 + 360 * num1 + 360 * 360 * num2;
var decoded0 = encoded / 1 % 360;
var decoded1 = encoded / 360 % 360;
var decoded2 = encoded / 360 / 360 % 360;

如果您使用BigInteger,那么在无限(或实际上很多)数字的情况下,您可以通过这种方式实现理论上的最佳编码。

或者,您可以使用支持2个以上备选方案的arithmetic coding变体。使用算术编码,您可以逐步编码数字并在可用时提取位。你只需要恒定的记忆。

如果您的数字不均匀分布(假设0是通常的两倍),算术编码器可以使用该知识来保存更多位。许多通用压缩机使用这种技术(其中包括LZMA)。

答案 1 :(得分:0)

对于您给出的特定示例,“方向基(360)日基(366)小时基(24)分基(60)',事实证明其中两个非常适合55位。 (360 x 366 x 24 x 60) 2 只是一个小于2 55 的微生物。因此,对于编码和解码,您只需使用乘法和除法(分别得到商和余数)。这可以使用64位算术完成,因此不需要大整数例程。实际上,55位中只有0.001位被浪费了!

因此对于范围为1..360,1..366,1..24和0..59的direction:day:hour:minute,序列{a:b:c:d, e:f:g:h}编码为(((((((a - 1) * 366 + (b - 1)) * 24 + (c - 1)) * 60 + d) * 360 + (e - 1)) * 366 + (f - 1)) * 24 + (g - 1)) * 60 + h 。要解码,请将除法的余数除以60,得到h。取该商,然后除以24除以得到g - 1,依此类推。

然后55位序列可以作为比特流连接,其中8个符合55个字节。

未使用的55位序列可用于终止序列。例如。所有1位,除最后一位之外的所有1位都为零,等等。可以使用两个不同的终结符来指示倒数第二个55位序列是否包含一个或两个向量。

做得更好的唯一方法是利用数字上的非均匀分布和/或连续向量之间的相关性。对于后者,您应该考虑这些数字中的一些或全部是否可能与先前向量中的相应数字接近或相同。如果存在这种相关性,那么您可以发送差异,并通过一些压缩,大大减少所需的总位数。