- ある整数をリトルエンディアンによって1bitずつ区切って並べたビットストリーム 1 0 1 0 0 0 1 1 を考えよう。これは8bitにまとめると、11000101 である。10進数に直せばこれは197である。このビットストリームと数値197との関係は
197 = 2^0 * 1 + 2^1 * 0 + 2^2 * 1 + 2^3 * 0 + 2^4 * 0 + 2^5 * 0 + 2^6 * 1 + 2^7 * 1
- となる。これでは論点が分かりにくいかもしれないので、プログラムで表してみる。ビットストリームの各桁が bs[i] によって表現可能であるとすると、
s = 0;
for (i = 0; i < 8; i++)
s += 2^i * bs[i];
- という計算でビットストリームをデコードできるというわけである。
- 一方、ビッグエンディアンで 11000101 をビットストリーム化すると、 1 1 0 0 0 1 0 1 になる。これをデコードするプログラムを考えれば、
s = 0;
for (i = 0; i < 8; i++)
s += 2^(7-i) * bs[i];
- ということになる。
- エンコードされた数値をデコードするという作業はきわめて基本的なものであって、そのプログラムをリトルエンディアンならすっきり書けるというわけである。2のベキの指数部分の数値とバイトストリームのインデックスが同じだというのはシンプルでとても気持ちがいい。しかもビッグエンディアンのほうに現れた 2^(7-i) なんていう式は、全体が8bitだと分かっていなければ書けない式である。リトルエンディアンならそんな情報は要らなくて、ただビットストリームの終わりまで計算すればそれでOKなのだ。なんて美しいんだろう。
- 自分はビットストリームなんて扱わない、バイト列で十分だ、というかもしれない。しかしそれでも、バイト列は256進法だとみなすことができるから、
s = 0;
for (i = 0; i < 4; i++)
s += 256^i * bs[i]; /* ここではバイトストリーム */
- と書ける。だからエンディアンの美しさはバイト列しか扱わなくても同じように現れる。
- もちろん僕は以下のようなビッグエンディアン向きのデコード方法も知っている。
s = 0;
for (i = 0; i < 8; i++)
s = s * 2 + bs[i];
- しかしなんというか、これはプログラミングテクニック的な問題である気がする。しかもこれは必ず前からデコードしなければいけない。ビットストリームが乱れてbs[0]から順番には届かず、先にbs[4]がきて、次にbs[1]が来て、みたいなことがもしあっても、とりあえずbs[0]が到着するまではこの方法ではデコード計算を開始できない(ビットストリームが乱れても、それがビットストリームのどの部分であるかの情報は、いっしょになって到着するとする・・・乱れるかもしれない状況ではそうやってパケットを作るのが基本である)。先に示した 2^(7-i) 方式であれば、とりあえず届いたパケットから処理してsに加算していくことが可能である。そういう意味でより基本的なデコード方法であると僕は信じる。