【问题标题】:C/C++ Compressing Integer to Short and Decompressing to Integer [closed]C/C++ 将整数压缩为短整数并解压缩为整数 [关闭]
【发布时间】:2021-06-30 04:07:33
【问题描述】:

我正在尝试找到一种方法通过网络发送一个长度为 16 位(短)的值,而其原始值由 32 位长度(整数)确定。

这个想法是通过压缩/解压缩客户端和服务器通信的值来尽可能地节省通过网络的流量大小。

我正在考虑获取整数值并将其位向右移动,在客户端它将它们向左移动。但是,当左边的 16 位丢失时,这不会带来准确的结果。

我不太熟悉压缩/解压缩算法,但我感觉这是可能的。

代码示例:

#include <stdio.h>
void printBits(size_t const size, void const * const ptr)
{
    unsigned char *b = (unsigned char*) ptr;
    unsigned char byte;
    int i, j;
    
    for (i = size-1; i >= 0; i--) {
        for (j = 7; j >= 0; j--) {
            byte = (b[i] >> j) & 1;
            printf("%u", byte);
        }
    }
    puts("");
}

////////////////////////////////////////
short Server(int value) {
    return value >> 3;
}

int Client(short value) {
    return value << 3;
}

int main()
{
    int value = 150000;
    printBits(sizeof(value), &value);
    printf("Before=%d, After=%d", Server(value), Client(Server(value)));
    return 0;
}

这带来了预期的结果,但是当通过从整数到短的转换从左侧剥离相关位时将不准确。

也许可以通过对这些值进行异或运算或对位进行不同的操作方式。我感觉它永远不会精确,但我的目标是尽可能接近原始结果。

【问题讨论】:

  • short Server(int value) { if (value &gt; numeric_limits&lt;int&gt;::max()) throw "oopsies"; if (value &lt; numeric_limits&lt;int&gt;::min()) throw "oopsies"; return static_cast&lt;short&gt;(value); }
  • 如果您发送的值不适合 16 位整数,那么您需要发送 32 位整数。要么先发送一个长度字节。
  • 现在你要发送很多数据;如果您发送的数据包大小小于默认数据包大小(约 1.4k),那么您还有剩余空间吗?
  • 显然您将发送大量此类数据,否则节省的费用不会很大。这些整数代表什么?它们是独一无二的吗?有很多重复吗?只有在利用数据的某些属性时,才能设计出有意义的压缩。 (除了先将整个数据包拉上拉链。)
  • 很明显,您不能在 16 位中存储 32 位值而不会丢失或无法表示某些值。一个 16 位无符号整数可以存储 0 到 65536 之间的值。你不能神奇地增加 16 位中的信息量。

标签: c++ c network-programming bit-manipulation


【解决方案1】:

对于 16 位,有 216 = 65,536 种可能的设置。每个位设置最多可以表示一个值。所以 16 位数据只能表示 65,536 个值。

32 位有 232 = 4,294,967,296 种可能的设置。如果您的 32 位数据使用了超过 65,536 个可以表示的可能值,则无法将其压缩为 16 位并在解压缩时始终恢复原始值。

选项包括:

  • 如果您的 32 位数据使用的值不超过 65,536 个,您可以创建一个代码,将每个使用的值映射到 0 到 65,535 之间的一个数字。编码值然后将数据压缩为 16 位,解码值将其解压缩。
  • 如果不需要完全准确,您可以将附近的 32 位值映射到单个 16 位值。例如,如果使用 0 到 150,000 之间的值,您可以右移两位以获得 0 到 37,500 之间的值,这将适合 16 位 unsigned short。您可以通过左移两位来近似恢复原始值。您也可以除以 3 而不是移位(相当于除以 4),这会在一定程度上减少错误,但在许多处理器中除法比移位花费更长的时间。除以 3 仍会产生适合 16 位的结果,因为 150,000/3
  • 不要使用压缩,因为将 32 位值压缩成 16 位是不可能得到想要的结果的。

关于 shift-and-losing-accuracy 解决方案:有时最好在解压后的值上加一点,以减少平均误差和最大误差。例如,100、101、102 和 103 都将被压缩到相同的值 25。然后通过乘以 4 进行简单恢复将产生 100。这对于 100 有 0、-1、-2 和 -3 的误差, 101, 102, 和 103,分别。 (平均误差幅度为 1½,最大值为 3。)如果我们相乘后加 1,则 25 解压缩为 101,然后误差为 +1、0、-1 和 -2(平均 1,最大 2)。

【讨论】:

    猜你喜欢
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 2021-05-14
    相关资源
    最近更新 更多