C/C++ 将整数压缩为短整型并解压为整数
C/C++ Compressing Integer to Short and Decompressing to Integer
我正在尝试找到一种方法通过网络发送一个长度为 16 位(短)的值,而其原始值由 32 位长度(整数)决定。
我们的想法是通过客户端和服务器通信的 compressing/decompressing 值尽可能地节省网络流量。
我正在考虑获取整数值并将其位向右移动,在客户端中它会将它们向左移动。但是当左边的16位丢失时,这将不会带来准确的结果。
我不太熟悉 compressions/decompression 算法,但我有一种很好的感觉,这是可能的。
代码示例:
#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;
}
这带来了预期的结果,但是当通过从整数到短整型的转换从左侧剥离相关位时,将不准确。
也许可以通过异或这些值或不同的方式对位进行操作。我觉得它永远不会精确,但我的目标是尽可能接近原始结果。
对于 16 位,有 216 = 65,536 种可能的设置。每个位设置最多可以表示一个值。所以16位数据只能表示65536个值。
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 < 65536。您也可以除以 2.3 以进一步减少误差,但这需要更多工作。
- 不要使用压缩,因为将 32 位值压缩成 16 位无法获得预期的结果。
关于shifting-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)。
我正在尝试找到一种方法通过网络发送一个长度为 16 位(短)的值,而其原始值由 32 位长度(整数)决定。
我们的想法是通过客户端和服务器通信的 compressing/decompressing 值尽可能地节省网络流量。
我正在考虑获取整数值并将其位向右移动,在客户端中它会将它们向左移动。但是当左边的16位丢失时,这将不会带来准确的结果。
我不太熟悉 compressions/decompression 算法,但我有一种很好的感觉,这是可能的。
代码示例:
#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;
}
这带来了预期的结果,但是当通过从整数到短整型的转换从左侧剥离相关位时,将不准确。
也许可以通过异或这些值或不同的方式对位进行操作。我觉得它永远不会精确,但我的目标是尽可能接近原始结果。
对于 16 位,有 216 = 65,536 种可能的设置。每个位设置最多可以表示一个值。所以16位数据只能表示65536个值。
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 < 65536。您也可以除以 2.3 以进一步减少误差,但这需要更多工作。 - 不要使用压缩,因为将 32 位值压缩成 16 位无法获得预期的结果。
关于shifting-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)。