ZigZag编码


发布于 2024-09-11 / 37 阅读 / 0 评论 /
ZigZag将有符号整数统一映射为无符号整数,再通过Varint编码规则达到数据压缩的效果

ZigZag是一种针对整数的编码算法。

1.ZigZag编码

编码就是将整数进行转换的过程。

1.1.编码规则

满足两个规则

(1)将整数的补码的最高位移动到最低位。

(2)如果是负数,则除符号位外,其他位取反;正数无须操作。

1.2.编码公式

可通过以下公式实现zigzag编码。

# 针对8位整数的编码
zigzag(n) = n>>7 ^ n<<1

# 针对32位整数的编码
zigzag(n) = n>>31 ^ n<<1

编码与整数的bit位数有关。

1.3.编码案例

32位整数11的编码过程

# 原码十进制
11

# 原码二进制
00000000,00000000,00000000,00001011

# 补码二进制
00000000,00000000,00000000,00001011

# 最高位移到最低位
00000000,00000000,00000000,00010110

# ZigZag编码
00000000,00000000,00000000,00010110

32位整数-11的编码过程

# 原码十进制
-11

# 原码二进制(负数用补码表示)
11111111,11111111,11111111,11110101

# 补码二进制
11111111,11111111,11111111,11110101

# 最高位移到最低位
11111111,11111111,11111111,11101011

# 除最后一位外(符号位),其他位取反
00000000,00000000,00000000,00010101

# ZigZag编码
00000000,00000000,00000000,00010101

正数的补码为原码本身,负数的补码为反码加1

可以看到,无论是正数还是负数,经过ZigZag编码后,高位大概率是0,可用于压缩。

2.ZigZag解码

解码就是将编码后的整数转换为原文本的过程。

2.1.解码规则

满足以下两个规则

(1)如果最低位是1,表示负数,除符号位外,其他位取反;如果最低位是0,则表示正数,无须操作

(2)将整数补码最低位移动到最高位

2.2.解码公式

可通过以下公式实现zigzag解码。

zigzag'(n) = (n>>>1) ^ -(n&1)

这里不需要考虑位数

2.3.解码案例

以下是一个正数的解码过程

# 二进制zigzag编码
00000000,00000000,00000000,00010110

# 最低位是1,表示正数,无须操作
00000000,00000000,00000000,00010110

# 最低位移到最高位
00000000,00000000,00000000,00001011

# 得到整数
11

以下是一个负数的解码过程

# 二进制zigzag编码
00000000,00000000,00000000,00010101

# 最低位是1,表示负数,其他位取反
11111111,11111111,11111111,11101011

# 最低位移到最高位
11111111,11111111,11111111,11110101

# 取补码(反码加1)
00000000,00000000,00000000,00001011

# 得到整数
-11

3.ZigZag适用场景

ZigZag仅从经验出发,认为较小的整数会有较大的概率出现,故设计编码策略:小整数对应的ZigZag码字短,大整数对应的ZigZag码字长。

但是,在特定的场景下,比如,要传输的整数为大整数居多,ZigZag编码的压缩效率就不理想了。