大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说Varint和Zigzag,希望您对编程的造诣更进一步.
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
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编码了。
但是,如何发现这种映射方法,目前还没有明白,希望大佬们可以在评论区留言解惑。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13803.html