zigzag
压缩zigzag 的原理就是压缩多余的因补位造成数据变大的问题,它的原理是把符号位向右移到在最前一位,对负数除最后一位经行求为非;正数求不变.
zigzag
压缩算法代码/**
* 把整数数据转换为zigzag 数据
* @param
*/
int int_to_zigzag(int n){
return (n <<1) ^ (n >>31);
}
zigzag
算法是在apache thrift
的JAVA
版 提取出来的,这里我只是做运算过程的展示,方便大家理解。注意下面的运算我是在16位的2字节经行演示,其他的位数类似。
- (-1)10=转成zigzag的步骤:
总结:
(-1)10
=(11111111_11111111_11111111_11111111)2
=(00000000_00000000_00000000_00000001)zigzag
(1)10=转成zigzag的步骤:
(1)10
= (00000000_00000000_00000000_00000001)2
= (00000000_00000000_00000000_00000010)zigzag
zigzag
解压对压缩后的二进制进行解压,需要判断第一位是不是为1,若为1则对除第一位进行位非,然后把第一位进行无符号向左位移到最左一位.
zigzag
解压演示任然以上面结果进行演示
(00000000_00000000_00000000_00000010)zigzag=(11111 =(1)10
(00000000_00000000_00000000_00000001)zigzag = (11111111_11111111_11111111_11111111)2=(-1)10
zigzag
解压算法代码优化的算法:
/**
* 把zigzag 解压位int
* @param n zigzag原始数据
*/
private int zigzagToInt(int n) {
return (n >>> 1) ^ -(n & 1);
}
(00000000_00000000_00000000_00000010)zigzag=(00000000_00000000_00000000_00000001)2 =(1)10
(00000000_00000000_00000000_00000001)zigzag
= (11111111_11111111_11111111_11111111)2= (-1)10
单纯的经行压缩,而并不能达到传输字节减少,本来16位的任然用的是16位的传输,32位的任然用32位的传输,因此有必要需要有对应的利用算法.把压缩后的无谓的0减少传输,才能达到压缩减少传输量的的效果.
/**
* zigzag 传输算法
* @param n zigzag数据
*/
private void write(int n) throws TException {
//数据缓冲池
final byte[] temp=null;
//缓冲数组大小
int idx = 0;
while (true) {
if ((n & ~0x7F) == 0) { //是否剩余8位
temp[idx++] = (byte)n;
break;
} else {
temp[idx++] = (byte)((n & 0x7F) | 0x80); 取低7位,并在第8位标记1
n >>>= 7;
}
}
//缓冲池输出
//trans_.write(temp, 0, idx);
}
粗略地解析传输算法是,把zigzag数据分成以7位字节分组,并在第八位插入一位标记位,组成一个8位的普通的传输位数据(TCP/IP最小的传输大小为8位).标记位的作用是表示该字节是否为最后数据字段,若不是则标记为0,若是则标记为1.
/**
* 解密算法
* @param buf 传输过来的字节数组
*/
private int read_from_buffer(byte[] buf){
//结果值
int result = 0;
//位移量
int shift = 0;
//数组位置
int off = 0;
while (true) {
byte b = buf[off];
result |= (int) (b & 0x7f) << shift;
if ((b & 0x80) != 0x80) break;
shift += 7;
}
}
传过来的应该是一组存储1 byte 大小的数据的数组.传过来的数据从第0个开始取后7位数字,然后向左位移n*7
(n为第几个数组),最后用位或|
连接起来,然后判断当前数组的第8位是不是为0,如果为0则继续,则下一个数组;如果为0,则表示到达最后一个有效数组,结束循环,返回连接好的数据.
Reference
小而巧的数字压缩算法:zigzag