zigzag编码的出现是为了解决varint对负数编码效率低的问题。zigzag编码的原理非常简单,就是将有符号整数映射为无符号整数。在实现上,映射通过移位即可实现,而不需要使用映射表来存储。

zigzag编码原理解析

对于正整数,可以把无意义的0去掉,只存储从1开始的"有效"数据,这样就可以压缩数据了。

例如,对于正整数1,其补码(当代计算机中实际按补码表示整数)按位展开,即为(00000000 00000000 00000000 00000001),显然,我们可以只用一个字节甚至1bit来存储有效数据。

负数的补码可没有这么容易压缩。

例如,对于负数-1,(11111111 11111111 11111111 11111111),全为1,并没有压缩的空间了啊!怎么办?

我们知道补码的最高位是符号位对于负数,符号位为1,它阻碍了对于无意义0的压缩;既然有阻碍,那就得想办法解决这个阻碍;是否可以将符号位移动到补码的最后,然后数据位整体左移1位,这样就能把这个“阻碍”解决呢?

(-1)10

(11111111 11111111 11111111 11111111)

符号位移动到最低位数据位整体相对左移1位

(11111111 11111111 11111111 11111111)移位

对于绝对值小的负数,冗余的前导1还是很多;似乎解决的并不彻底

数据位按位取反,符号位保持不变

(00000000_00000000_00000000_00000001)取反

经过移位和取反操作后,-1被“编码”成了1。如此,便能很好的压缩数据,彩!

对于非负整数,只需完成 符号位移到最低位,数据位整体左移1位

我们再来看看整数1通过同样的处理后被“编码”成什么值。

(1)10

(00000000 00000000 00000000 00000001)补

(00000000 00000000 00000000 00000010)移位

经过移位操作后,1被“编码”成了2。

似乎能得到这样的结论:

  1. 对于负数,经过移位和数据位取反,也能将绝对值小的负数进行压缩;

  2. 对于非负数,经过移位,也可以压缩;

那么又有一个问题来了,这两种结论怎样在代码实现层面合二为一呢?

知识点:

算术左移低位补0;算术右移,若符号位为0,高位补0;若符号位为1,高位补1;

对于n=-1(32位),(11111111 11111111 11111111 11111111)

n << 1, a= (11111111 11111111 11111111 11111110),数据位整体左移1位

n >> 31,b= (11111111 11111111 11111111 11111111),符号位移到最低位

负数的算数右移高位补1,所以右移31位后,b为全1,这点非常重要

c=a^b, c= (00000000 00000000 0000000 00000001),将-1“编码”成了1,与前面的分析一致

因为a中数据位冗余的前导1刚好与b中数据位冗余的前导1相对应,那么进行异或操作时,就能将这些冗余的前导1消除掉,数据位完成了取反动作,这样便能压缩数据了

对于n=1(32位),(00000000 00000000 00000000 00000001)

n << 1, a= (00000000 00000000 00000000 00000010),数据位整体左移1位

n >> 31,b= (00000000 00000000 00000000 00000000),符号位移到最低位

非负数的算数右移高位补0,所以右移31位后,b全为0,这点非常重要

c=a^b,c= (00000000 00000000 00000000 00000010),将1“编码”成了2,与前面的分析一致

因为0^0还是0,所以对于正整数,异或操作没有影响。

综上所述,对于32位整数,(n<<1)^(n>>31),即能实现zigzag编码。如此精妙,彩!

搞懂了zigzag的编码原理,当然得知道怎样解码,否则就不能还原真实数值了。

zigzag解码原理解析

对于zigzag编码的值2,(00000000 00000000 00000000 00000010)

n >> 1, a = (00000000 00000000 00000000 00000001),整体右移,还原数据位

-(n&1),b = -(2&1)10 = -(0)10 = (00000000 00000000 00000000 00000000),最低位按位与,取负号,还原符号位

c=a^b,c = (00000000 00000000 00000000 00000001),将zigzag编码值2 解码还原成了1

对于zigzag编码的值3,(00000000 00000000 00000000 00000011)

n >> 1, a = (00000000 00000000 00000000 00000001),整体右移,还原数据位

-(n&1),b = -(3&1)10 = -(1)10 = (11111111 11111111 11111111 11111111),最低位按位与,取负号,还原符号位

c=a^b,c = (11111111 11111111 11111111 11111110),将zigzag编码值3 解码还原成了-2

综上所述,对于32位整数,(n>>1)^-(n&1),即能实现zigzag解码。

c实现

// zigzag 编码
uint32_t zigzag_encode_32(int32_t val)
{return (uint32_t)((val<<1)^(val>>31));
}// zigzag解码
int32_t zigzag_decode_32(uint32_t val)
{return (int32_t)((val>>1) ^ -(val&1));
}

运行结果

$ ./a.out -1
input num:-1
zigzag code:1,0x1
zigzag decode:-1,0xffffffffffffffff
$ ./a.out -2147483648
input num:-2147483648
zigzag code:4294967295,0xffffffff
zigzag decode:-2147483648,0xffffffff80000000
$ ./a.out 2147483647
input num:2147483647
zigzag code:4294967294,0xfffffffe
zigzag decode:2147483647,0x7fffffff

所谓数据压缩,说白了就是将不重要的数据忽略或舍弃;由于计算机中只有0和1,本质上就是将无意义的0丢弃,而起到数据压缩的目的。

zigzag算法详解相关推荐

  1. Matlab人脸检测算法详解

    这是一个Matlab人脸检测算法详解 前言 人脸检测结果 算法详解 源代码解析 所调用函数解析 bwlabel(BW,n) regionprops rectangle 总结 前言 目前主流的人脸检测与 ...

  2. 图论-最短路Dijkstra算法详解超详 有图解

    整体来看dij就是从起点开始扩散致整个图的过程,为什么说他稳定呢,是因为他每次迭代,都能得到至少一个结点的最短路.(不像SPFA,玄学复杂度) 但是他的缺点就是不能处理带负权值的边,和代码量稍稍复杂. ...

  3. C++中的STL算法详解

    1.STL算法详解 STL提供能在各种容器中通用的算法(大约有70种),如插入.删除.查找.排序等.算法就是函数模板,算法通过迭代器来操纵容器中的元素.许多算法操作的是容器上的一个区间(也可以是整个容 ...

  4. 粒子群(pso)算法详解matlab代码,粒子群(pso)算法详解matlab代码

    粒子群(pso)算法详解matlab代码 (1)---- 一.粒子群算法的历史 粒子群算法源于复杂适应系统(Complex Adaptive System,CAS).CAS理论于1994年正式提出,C ...

  5. 基础排序算法详解与优化

    文章图片存储在GitHub,网速不佳的朋友,请看<基础排序算法详解与优化> 或者 来我的技术小站 godbmw.com 1. 谈谈基础排序 常见的基础排序有选择排序.冒泡排序和插入排序.众 ...

  6. 目标检测 RCNN算法详解

    原文:http://blog.csdn.net/shenxiaolu1984/article/details/51066975 [目标检测]RCNN算法详解 Girshick, Ross, et al ...

  7. Twitter-Snowflake,64位自增ID算法详解

    Twitter-Snowflake,64位自增ID算法详解 from: http://www.lanindex.com/twitter-snowflake%EF%BC%8C64%E4%BD%8D%E8 ...

  8. 数据结构与算法详解目录

    数据结构与算法详解是一本以实例和实践为主的图书,主要是经典的数据结构与常见算法案例,来自历年考研.软考等考题,有算法思路和完整的代码,最后提供了C语言调试技术的方法. 后续配套微课视频. 第0章  基 ...

  9. [搜索]波特词干(Porter Streamming)提取算法详解(2)

     接[搜索]波特词干(Porter Streamming)提取算法详解(1), http://blog.csdn.net/zhanghaiyang9999/article/details/4162 ...

最新文章

  1. 生成唯一字符串算法_面试官问:在分布式场景,生成唯一ID,你有几种方案?...
  2. 关于 sql server 基本使用的建议
  3. 商汤科技开源DAVIS2017视频目标分割冠军代码
  4. 前端_JavaScript_面向对象编程
  5. python怎么做回归分析_如何在Python中进行二维回归分析?
  6. 【软件工程】用于IS规划的SWOT方法
  7. 详细分析已遭利用的 Desktop Window Manager 0day
  8. 蓝桥杯 ALGO-96 算法训练 Hello World!
  9. 也来谈一谈js的浅复制和深复制
  10. 一个类的类类型是Class类的实例,即类的字节码
  11. Xcode和macOS对应关系查询网址
  12. CMD操作查看电脑IP
  13. Mentor-dft 学习笔记 day1--overview部分
  14. cdlinux U盘启动制作方法
  15. 基于51单片机的单词记忆测试器
  16. Filebeat实现简单格式化数据dissect
  17. 港科夜闻|香港科大陈启峰教授:人工智能与深度学习交织-从竞赛开始,到无尽钻研...
  18. Spring Cloud之Hystrix服务容错
  19. 固态硬盘在线测试软件,ssd测试软件,详细教您ssd测试软件
  20. 多用户在线书签管理工具My-BookMark

热门文章

  1. Impala 三大组件:Impala Daemon, Impala Statestore, Impala Catelog
  2. 舞台灯光计算机控制,舞台灯光的操作
  3. 任正非详解华为不上市与家人不接班问题
  4. 徐宗本院士:智能制造的大数据机遇与挑战
  5. NFS服务器的配置与管理
  6. [设计模式](十):策略模式(Strategy)与模板模式(Template)详解及二者间区别介绍(两种父子类行为模式)
  7. angr学习之ctf练习
  8. Python学习资料全面总结,真的对零基础很有用
  9. PhotoMOS输出光电耦合器的概要
  10. 疫情数据分析平台(五):中国疫情地图绘制