Varint和Zigzag

Varint和ZigzagVarint就是一种对数字进行编码的方法,编码后二进制数据是不定长的,数值越小的数字使用的字节数越少。例如对于int32_t,采用Varint编码后需要1~5个字节,小的数据使用1个字节,大的数字使用5个字节。基于实际场景中小数字的使用远远多于大数字,因此通过Varint编码对…

Varint就是一种对数字进行编码的方法,编码后二进制数据是不定长的,数值越小的数字使用的字节数越少。例如对于int32_t,采用Varint编码后需要1~5个字节,小的数据使用1个字节,大的数字使用5个字节。基于实际场景中小数字的使用远远多于大数字,因此通过Varint编码对于大部分场景可以起到一个压缩的效果。

无符号

Varint中的每个字节的最高位bit有特殊的含义,如果该位为1,表示后续的字节也是该数字的一部分,如果该位为0,则结束。其他的7个bit都用来表示数字。因此小于128的数字都可以用一个字节表示。大于128的数字,会用两个字节。

例如整数1的表示,仅需一个字节:

0000 0001

例如300的表示,需要四个字节:

1010 1100 0000 0010

Varint和Zigzag

def encode(num):
    buf = ""
    while True:
        n = num & 0x7f
        num >>= 7
        if num != 0:
        	n |= 0x80
            buf += chr(n)
        else:
            buf += chr(n)
            break
    return buf

def decode(buf):
    num = 0
    shift = 0
    i = 0
    while True:
        n = ord(buf[i])
        i += 1
        num |= (n & 0x7f) << shift
        shift += 7
        if not (n & 0x80):
            break
    return num

有符号

在有符号的情况下,需要使用有符号数到无符号数的映射,Zigzag编码。

详细的映射表如下:

Signed Original Encoded As
0 0
-1 1
1 2
-2 3
2 4
2147483647 4294967294
-2147483647 4294967295
inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
  // Note: the right-shift must be arithmetic
  return (n << 1) ^ (n >> 31);
}

inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
  return (n >> 1) ^ -static_cast<int32>(n & 1);
}

inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
  // Note: the right-shift must be arithmetic
  return (n << 1) ^ (n >> 63);
}

inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
  return (n >> 1) ^ -static_cast<int64>(n & 1);
}

通过Zigzag编码后,就可以对负数进行varint编码了。

但是,如何发现这种映射方法,目前还没有明白,希望大佬们可以在评论区留言解惑。

www.cnblogs.com/jacksu-tenc…

izualzhy.cn/protobuf-en…

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13803.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注