varint原理 - 正数的编码和解码

简言

1. varint即 variable int,也就是变长的整型,在mysql,levelDB,protobuf中都有使用

2. varint编码的优点是对数值较小的数进行编码后占用字节较少。而我们常用的int32,int64之类,无论数字多大,都固定占4字节,8字节

3. varint编码的缺点是对数值较大的数和负数进行编码后占用字节较多,最多可能要占10个字节(表示负数的时候)

4. 因为生活中真实用到的数字往往都不大且是正数,所以综合优点缺点varint还是能节省一些空间

编码原理

varint 对数字的二进制,从右往左,每7位分割成一块

如果不是最后一块,则最左边补1,组成一个字节

如果是最后一块,则左边缺的全部补0,组成1个字节

最终保存的时候,根据分割块的顺序依次从左往右

解码原理

读取字节流后,从左往右,逐个字节判断

如果该字节最左边为1,说明varint值没读取完,后面的字节还是本varint的值,继续读。本字节最左边的1去掉后,剩下的7位留作备用

如果该字节最左边为0,说明varint值读取完毕

最终,根据分割块的顺序依次从右往左填,组成的字节流按int型解析即可

举例(为了方便大家看,从右往左,每7位一个颜色)

测试用例1

数字5,二进制101

编码过程:

1. 从右往左依次取7位,第一次尝试取7位时,由于只有3位,所以只分割出来1块,也就是最后一块,根据规则前面补0,得到00000101

所以,varint表示法是00000101

跟原来二进制一样,所以[0~255]之间的数字只占用1个字节

解码过程:

1. 从左往右,逐个字节判断,由于只有1个字节,且最高位为0,说明varint值已读取完毕,所以最终的顺序也就是00000101,按int型解析,即5

测试用例2

数字130,按无符号,二进制10000010

编码过程:

1. 从右往左依次取7位,第一次取出来的0000010,因为前面还有数字1,说明自己不是最后一块,根据规则左边补1,得到 10000010

2. 第二次尝试取7位,只取出来1,因为前面已经没数字了,这里是最后一块了,根据规则前面补0,得到00000001

把这些分割后新组成的块,从左往右

所以,varint表示法是10000010   00000001

解码过程:

1. 从左往右,逐个字节判断,第一个字节10000010最高位为1,说明后面字节还有,需要继续读。这里去掉最左边的标志1,剩下的0000010备用

2. 读第二个字节 00000001最高位为0,说明后面没了,本字节就是varint的最后一个字节了。去掉最左边的标志0,剩下的0000001备用

3. 根据分割块的顺序,从右往左填,组成的字节流00000010000010,去掉前面无意义的0,剩下10000010,根据无符号int型解析,得到130

测试用例3

数字12345678,二进制101111000110000101001110

编码过程:

1. 从右往左依次取7位,第一次取出来的1001110,因为自己不是最后一块,根据规则左边补1,得到11001110

2. 第二次取出来的1000010,因为自己不是最后一块,根据规则左边补1,得到11000010

3. 第三次取出来的1110001,因为自己不是最后一块,根据规则左边补1,得到11110001

4. 第四次取出来的101,因为自己是最后一块,根据规则左边补0,得到00000101

把这些分割后新组成的块,从左往右

所以,最终varint表示法是11001110  11000010  11110001   00000101

解码过程:

1. 从左往右,逐个字节判断,第一个字节11001110最高位为1,说明后面字节还有,需继续读。

这里去掉最左边的1,剩下的1001110备用

2. 读第二个字节11000010 最高位为1,说明后面字节还有,需继续读。这里去掉最左边的1,剩下的1000010备用

3. 读第三个字节11110001 最高位为1,说明后面字节还有,需继续读。这里去掉最左边的1,剩下的1110001备用

4. 读第四个字节00000101 最高位为0,说明后面没了,本字节就是varint的最后一个字节了。去掉最左边的标志0,剩下的0000101备用

5. 根据分割块的顺序,从右往左填,组成的字节流0000101111000110000101001110

去掉前面无意义的0,剩下101111000110000101001110,按int型解析得到12345678

这篇博客我们讲了varint的实现原理

以正数举了3个例子,给大家分析了正数的编码、解码过程,下一篇我们讲varint对负数的处理

varint原理 - 负数的编码和解码_YZF_Kevin的博客-CSDN博客

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值