5分でわかる(かもしれない)圧縮の基本

大規模データを日常的に扱う人にとって、データ圧縮は基本。絶対ないと困るわけではないけど、あると格段に世界が広がる。ドラクエで言うところのルカニみたいなもの。
でも圧縮というとデータをバイナリで持たないといけないとか、なんとなく面倒なので目を背けがち。そこで5分でわかるような感じで説明を書いておく。


基本的な圧縮の方法は差分圧縮というのがある。今回はこれを説明する。
char型のデータが8つ並んでいると考える。

6 3 2 1 7 5 4 8

とりあえずバイナリにしてみる。便宜上、縦に書く。

        6 3 2 1 7 5 4 8
        ===============
  1の位:0 1 0 1 1 1 0 0
  2の位:1 1 1 0 1 0 0 0
  4の位:1 0 0 0 1 1 1 0
  8の位:0 0 0 0 0 0 0 1
 16の位:0 0 0 0 0 0 0 0
 32の位:0 0 0 0 0 0 0 0
 64の位:0 0 0 0 0 0 0 0
128の位:0 0 0 0 0 0 0 0

char型は8bitなので二進数で1の位から128の位まである。ここで下の方にすごい勢いで0が並んでいて無駄っぽい。消してしまいたい。つまり

        6 3 2 1 7 5 4 8
        ===============
  1の位:0 1 0 1 1 1 0 0
  2の位:1 1 1 0 1 0 0 0
  4の位:1 0 0 0 1 1 1 0
  8の位:0 0 0 0 0 0 0 1
        ===============
        4桁使ったよ

こうしたい。のでそうする。とりあえず4桁使ったよ、とメモっておけばOK。
char型より小さい型なんてないのにどうやってプログラミングするの?と思うかもしれない。実はこのためにchar型の変数を8個並べた。つまり、1の位の8bit分、2の位の8bit分・・・をそれぞれchar型で持てばよい。
すると同様に

        0 3 2 1 2 2 0 1
        ===============
  1の位:0 1 0 1 0 0 0 1
  2の位:0 1 1 0 1 1 0 0
        ===============
        2桁使ったよ
        96 48  6 70  2 99 54  9
        =======================
  1の位: 0  0  0  0  0  1  0  1
  2の位: 0  0  1  1  1  1  1  0
  4の位: 0  0  1  1  0  0  1  0
  8の位: 0  0  0  0  0  0  0  1
 16の位: 0  1  0  0  0  0  1  0
 32の位: 1  1  0  0  0  1  1  0
 64の位: 1  0  0  1  0  1  0  0
        =======================
        7桁使ったよ

というのができる。見てわかる通り、大きな数が出てくるほど使う桁数が大きい。のでできるだけ小さい数で済ませたい。
そこで差分をとる。つまり

         1  3  5  8 11 12 15 19
        =======================
  1の位: 1  1  1  0  1  0  1  1
  2の位: 0  1  0  0  1  0  1  1
  4の位: 0  0  1  0  0  1  1  0
  8の位: 0  0  0  1  1  1  1  0
 16の位: 0  0  0  0  0  0  0  1
        =======================
        5桁使ったよ

というデータがあったら

   1  3  5  8 11 12 15 19
=> 1  2  2  3  3  1  3  4

とすれば

         1  2  2  3  3  1  3  4
        =======================
  1の位: 1  0  0  1  1  1  1  0
  2の位: 0  1  1  1  1  0  1  0
  4の位: 0  0  0  0  0  0  0  1
        =======================
        3桁使ったよ

となる。5桁から3桁に減った。8個の数に5桁使えば、40bit、3桁なら24bitなので16bit分圧縮された。これが差分圧縮。簡単便利すばらしい。