Elias gamma code(eliasγ码/以利亚加玛码) 一种正整数通用编码

Elias gamma code

1.简介

Elias gamma code 是一种用于正整数的通用编码,由Peter Elias发明。常被用于无法事先得知上界的正整数,即一种变长编码方式。
CocosBuilder的ccb文件中的整数正是采用了这种编码方式,被编码到了ccbi文件中(ccbi是二进制文件)。
在Cocos2dx引擎中,CCBReader利用了Elias gamma code 的解码方式,将ccbi文件中的整数解析出来。

2.名词解释

有效位:一个二进制数从左往右第一个为1的位及其之后所有位叫有效位,其余称无效位,如:0 000 1 0001
floor:向下取整,即[X,X+1)区间中的所有数都取X;

3.编码原理

我们都知道,int变量通常占4个字节(byte),每个字节8位(bit),共占32位,在计算机中以二进制存储。如果能剔除所有二进制数无效位,再将剩下有效位 紧密排列写进二进制文件里,就可以大大减少空间占用。这就是原理,很简单。

举个栗子:
剔除前:(17,11)10=(0000 0000 000 1 0001 ,0000 0000 0000 1011)2---->剔除后 (1 0001,1011)2

我们看到17的有效位个数为 5,无效位个数为27。11的有效位个数是 4,无效位个数是28。
然后对17和9剔除无效位,剔除后共占9位,剔除前,两个二进制数占了64位。

但是又考虑到解码时必须指明被编码了的有效位个数,不然解码器不知道应该读到哪一位为止。还要进行进一步处理,即在二进制数的 有效位 前 放置 [有效位个数-1] 个0,此时编码完成。
接着上面的例子,在17前加 4个0,在11前加 3个0。

(1 0001,1011)2---->编码结果:(0 000 1 0001, 000 1011 )2

最终,只用16位对原64位的两个数完成了编码。

4.解码原理

为什么加的0要比有效位个数少 1 ? 跟解码原理有关。
解码时,从左往右读二进制串,一次读一位,边读边累计0的个数,记为 n 。当读到第一个有效位时,再继续往后读 n 位,即可完整读出一个整数的elias gamma编码。这正是 “在每个数的有效位前放置[有效位个数-1]个0” 的原因。
通过统计0的个数,解码器就能知道遇到第一个有效位后,还剩几个有效位要读。

看例子,编码后17和11的二进制码关于有效位对称,17和11的第一个有效位左右均是 n位:
(0 0001 0001000 1011)2

这样我们就能在二进制流中准确地读出一个又一个的elias gamma编码。读出编码后,再通过 或运算把编码的每一位映射到int变量的对应位上,即可还原该整数,完成解码。

5.百度的描述

前方介绍了通俗理解的编码过程。百度是这么描述的:

5.1 对于待编码正整数X>=1 :
令N=floor(log~2~X),故 2^N^<=X<=2^N+1^;
输出N个0比特
接着输出X的二进制表示
5.2 对于待解码正整数X>=1 :
读取并计数0比特直到第一个1比特出现,假设计数为N;
从第一个1比特之后,再读取 N 个比特,并将之还原成十进制正整数,令之为 M
最终解码为 2^N^+M

6.特别注意

6.1 从编码原理处可得,整数0不能用这种编码方式。

那要想对0进行编码怎么办? 我们可以在编码前进行加1处理,解码后再减1处理。

编码前,对整数+1,使0,1,2,3...->1,2,3,4...,再进行编码。
解码后,对所得整数-1,使 1,2,3,4...->0,1,2,3...,即可还原。
6.2 这种编码只适用正整数编码,

那要对有符号整数进行编码怎么办? 我们可以通过分段函数把有符号整数一一映射成正整数。
编码前,

对整数X>=0,进行映射X=2*X+1,使0,1,2,3...->1,3,5,7...
对整数X<0,进行映射X=-2*X,使-1,-2,-3...->2,4,6...

解码后,判断所得整数的奇偶性,利用函数,即可还原。

你可能感兴趣的:(Cocos2dx,CocosBuilder)