Elias Delta编码
Elias Delta编码、Elias delta code是一种用于正整数之通用编码。该码由彼得·埃利亚斯发明。
编码
对于待编码正整数 X≥1:
- 令 N=⌊log2 X⌋ ,故 2N ≤ X < 2N+1
- 令 L=⌊log2 N+1⌋ ,故 2L ≤ N+1 < 2L+1
- 输出 L 个零比特,接着输出
- N+1 之 L+1 比特二进制数,接着输出
- X 的最后 N 个比特。
另一个等价的编码方式为:
要对 进行编码,以利亚戴尔达码必须使用 个比特。
以下为一编码对照表:
数 | N | N+1 | 编码 | 代表之概率 |
---|---|---|---|---|
1 = 20 | 0 | 1 | 1 |
1/2 |
2 = 21 + 0 | 1 | 2 | 0 1 0 0 |
1/16 |
3 = 21 + 1 | 1 | 2 | 0 1 0 1 |
1/16 |
4 = 22 + 0 | 2 | 3 | 0 1 1 00 |
1/32 |
5 = 22 + 1 | 2 | 3 | 0 1 1 01 |
1/32 |
6 = 22 + 2 | 2 | 3 | 0 1 1 10 |
1/32 |
7 = 22 + 3 | 2 | 3 | 0 1 1 11 |
1/32 |
8 = 23 + 0 | 3 | 4 | 00 1 00 000 |
1/256 |
9 = 23 + 1 | 3 | 4 | 00 1 00 001 |
1/256 |
10 = 23 + 2 | 3 | 4 | 00 1 00 010 |
1/256 |
11 = 23 + 3 | 3 | 4 | 00 1 00 011 |
1/256 |
12 = 23 + 4 | 3 | 4 | 00 1 00 100 |
1/256 |
13 = 23 + 5 | 3 | 4 | 00 1 00 101 |
1/256 |
14 = 23 + 6 | 3 | 4 | 00 1 00 110 |
1/256 |
15 = 23 + 7 | 3 | 4 | 00 1 00 111 |
1/256 |
16 = 24 + 0 | 4 | 5 | 00 1 01 0000 |
1/512 |
17 = 24 + 1 | 4 | 5 | 00 1 01 0001 |
1/512 |
解码
以利亚戴尔达码之解码遵循下列步骤:
- 读取并计数零比特直到第一个一比特出现,假设共有 L 出现
- 从第一个一比特之后,再读取 L 个比特,并将已读取之 2L+1 个比特还原成十进制正整数。假设该正整数为 N+1
- 再读取 N 个比特并将之还原成十进制正整数,令之为 M
- 最终解码为 2N+M
举例:
001010011 1. 最左方有兩個零位元 001 2. 再讀取兩個位元 00101 3. 還原 00101 = 5 4. 再讀取 N = 5 − 1 = 4 個位元 0011 = 3 5. 解碼為 = 24 + 3 = 19
示例代码
编码
void eliasDeltaEncode(char* source, char* dest)
{
IntReader intreader(source);
BitWriter bitwriter(dest);
while (intreader.hasLeft())
{
int num = intreader.getInt();
int len = 0;
int lengthOfLen = 0;
for (int temp = num; temp > 0; temp >>= 1) // calculate 1+floor(log2(num))
len++;
for (int temp = len; temp > 1; temp >>= 1) // calculate floor(log2(len))
lengthOfLen++;
for (int i = lengthOfLen; i > 0; --i)
bitwriter.outputBit(0);
for (int i = lengthOfLen; i >= 0; --i)
bitwriter.outputBit((len >> i) & 1);
for (int i = len-2; i >= 0; i--)
bitwriter.outputBit((num >> i) & 1);
}
bitwriter.close();
intreader.close();
}
解码
void eliasDeltaDecode(char* source, char* dest)
{
BitReader bitreader(source);
IntWriter intwriter(dest);
while (bitreader.hasLeft())
{
int num = 1;
int len = 1;
int lengthOfLen = 0;
while (!bitreader.inputBit()) // potentially dangerous with malformed files.
lengthOfLen++;
for (int i = 0; i < lengthOfLen; i++)
{
len <<= 1;
if (bitreader.inputBit())
len |= 1;
}
for (int i = 0; i < len-1; i++)
{
num <<= 1;
if (bitreader.inputBit())
num |= 1;
}
intwriter.putInt(num); // write out the value
}
bitreader.close();
intwriter.close();
}
一般化
以利亚戴尔达码并不适用于零或负整数。一个一般化的方式是在最左侧先加一个一比特,解码时再行扣掉。另一个方法是在编码前将所有整数映射至正整数,例如:(0, 1, −1, 2, −2, 3, −3, ...) 对应至 (1, 2, 3, 4, 5, 6, 7, ...)。
参考项目
- Elias, Peter (March 1975). "Universal codeword sets and representations of the integers". IEEE Transactions on Information Theory 21 (2): 194–203.
- Classical and Quantum Information Theory: An Introduction for the Telecom ...(页面存档备份,存于互联网档案馆)
- Database Systems for Advanced Applications: 15th International Conference ...(页面存档备份,存于互联网档案馆)
- Web Data Mining: Exploring Hyperlinks, Contents, and Usage Data(页面存档备份,存于互联网档案馆)