十進の一桁は 3.32 ビットに値する

ロカポブログさんから話題をいただいて、情報量に関してエントリしてみます。それにからめて、Shapefile における DBF ファイル内部の数値表現についても書いてみました。

精度1mで情報を取るのと、精度10mで情報を取るのでは、元の精度を再現するのに必要な情報量は当たり前ですが10倍になります。

ロカポ ブログ: 経路やエリア情報の圧縮技術を開発、特許出願しました。LocaParam改めLocaPorter。

hatenaブックマークで指摘いただきました(ご指摘感謝!)
> 「「精度1mで情報を取るのと、精度10mで情報を取るのでは、元の精度を再現するのに必要な情報量は当たり前ですが10倍になります。」→ダウト! :-)
そのとおりです!すみません。
情報量という意味ではlog2(10) ≒3.3219倍です。(logの底は2)

ロカポ ブログ: 訂正!

「3.3219倍」というより、「プラス3.3219」と言った方が誤解が少なくなると思います。
情報量はかけ算というよりも足し算感覚になりますね。
そこで、(営業的にキャッチーであるかどうかは置いておいて、)技術的に正しい言い方は、

位置の精度を一桁増やすことは、情報量が 3.32 ビット増えることを意味します。

というあたりになるかと思います。

簡単な検算

log を使って数値の桁数を算出する、高校数学でよく使われる例の論理を使って、検算してみます。
unsigned byte は MAX が 255 なのですから、2桁強3桁弱の表現能力があります*1ね。このことは、8 / 3.32 = 2.41 であることと整合しています。unsigned byte は、2.41 桁の十進数値を表現する能力がある、ということですね。
では、16bit unsigned ではどうなるかというと、16 / 3.32 = 4.82 となりますので、十進数値で 4 桁強、5桁弱、どちらかというと5桁に近いあたりに MAX があるはずです。
実際、16bit unsigned というのは Java でいう char ですから、JRuby を通訳者として Java に聞いてみますと、

$ jirb
irb(main):001:0> require 'java'
=> true
irb(main):002:0> import java.lang.Character
=> Java::JavaLang::Character
irb(main):003:0> Character::MAX_VALUE
=> 65535

と、実際に4桁の数値はすべて表現でき、5桁の数値の過半数は表現できることが分かります。

蛇足

十進一桁が 3.32 ビットに値することは、二進化十進数(BCD)が4ビットを使うことに繋がります。

十進の桁数なんて?

十進法での桁数なんて、Nao さんが

表示上何桁必要かは、何進法を使うかで変わります。

ロカポ ブログ: 訂正!

とおっしゃるとおり、また計算機の内部では通常二進的に処理が行われるので、計算機の内部では気にする必要はないのです。しかし、地理情報の分野ではそれがまだ問題になる場合があるのです。
それは、Shapefile の属性データです。Shapefile の属性データは DBF (dBase の) ファイルに記録されます。そして、DBF では数値は結局文字列として保存されます*2。実際、Shapefile の属性データの定義域を指定する場合には、"Integer (9.0)", "Real (33.31)"などと、「十進の桁数」を使います*3
Shapefile は本当にとてもレガシーさあふれる符号化法です。.shp ファイルの内部では、リトルエンディアンとビッグエンディアンを使い分けて混在させていたりします。ご興味のあるかたは ESRI による Shapefile Technical Description をご覧ください。

*1:散文的な表現で申し訳ないです。2桁の数値のすべて 0-99 のすべてを表現できるが、3桁の数値のすべて 0-999 は表現できないという意味です。

*2:私が調べる限り。Shapefile では DBF の Integer と Real が使われていて、これらは最終的には文字列っぽく符号化されているみたいです。すみません、ここ、ツッコミどころかもしれません。

*3:なので、Shapefile の属性に浮動小数点数を格納しようとすると、うれしくないことが起こる場合があるかもしれません(要検証。あとで書くかもしれません。)。DBF ファイルの中で固定小数点数として記録されてしまうためです。