delta符号

先日gamma符号を紹介したので、今度はdelta符号を。

参考:gamma符号

delta符号はgamma符号と似ているのだが、大きな数値のときにgamma符号より少ないbitで済むように改良されている。一方で小さい数値の時はgamma符号のほうが効率が良い。


具体的に言うと、delta符号では数値を二進数にした時のbit数に対してさらにgamma符号を適用する。そしてその後ろに数値の二進数の先頭の1を除いたものをつける。(数値の二進表記は先頭が常に1であることに注意。常に1なので省いても大丈夫)つまり

数値	二進数	gamma符号	二進数のbit数	bit数のgamma符号	delta符号
1	1	1		1		1			1
2	10	010		2		010			0100
3	11	011		2		010			0101
4	100	00100		3		011			01100
5	101	00101		3		011			01101
6	110	00110		3		011			01110
7	111	00111		3		011			01111

復号化するときは始めにgamma符号を復号化すると、数値のbit数がわかるので、そのbit数分をひとつの数値として復号化すれば良い。例えば

01110
=> [0] 1110        # 0が1つ続いている
=> [0] [11] 10     # 1と、その後ろ1bitを分がひとつの数値
=> (3) 10          # 11を復号化して3になる
=> (3) [1] 10      # 1が省略されているので足す
=> [110]           # 3bit分をひとつの数値として復号化する
=> (6)

となる。2段階で復号化しているので小さな数値では冗長な表現のためdelta符号の方がgamma符号より長くなってしまうが大きな数値ではdelta符号のほうが短くなる。例えば、以下の通り(カッコ内はbit数)

数値	gamma符号			delta符号
1	1                   (1)		1                (1)
5	00101               (5)		01101            (5)
10	0001010             (7)		00100010         (8)
50	00000110010         (11)	0011010010       (10)
100	0000001100100       (13)	00111100100      (11)
500	00000000111110100   (17)	000100111110100  (15)
1000	0000000001111101000 (19)	0001010111101000 (16)

ちなみにunary符号では数値+1が必要なbit数なので、例えば数値が1000だとunary符号で1001bit、gamma符号で19bit、delta符号で16bit必要。gamma符号、delta符号が如何に効率が良いかがわかる。とはいえunary符号には単純であるという強みが有り、rank、selectなどの操作を付加したsuccinct bit vectorを作るときはunary符号のほうが圧倒的に簡単になる。