情報処理概論T バイナリにまつわるお話

宣言文でこれまで扱ってきた整数型,実数型の変数を扱ってきた.実数の場合,デフォルトでは4バイトだが我々は8バイトにしていた.
結局このバイトとは何ですか,という疑問があると思う.まずはバイナリの話の前にそこらへんについて解説する.


ビットとバイト

まずは最近聞くことが多くなったであろうビットについて.32ビットOSから64ビットOSになったとか最近ではよく聞くが
だいたいは「できることが増えた」くらいの印象しかないはず.結局なんですかということになる.そもそもビットとは
パソコン内部で使用されるデータの最小単位のことである.
例えば,パソコン内部では電圧の高低を0か1かという2進数で表現している.この2進数の一桁を
ビットと呼ぶ.

バイトとビットの関係は
1バイト=8ビット
4バイト=32ビット
8バイト=64ビット
ということになっている.

1バイトで考えてみる.上の関係から1バイトは8ビット,これは2の8乗で数字を表現するということと同義である.
どういうことかというと

表現したい数字 = a * 20 + b * 21 + c * 22 + d * 23 + e * 24 + f * 25 + g * 26 + h * 27
※a〜hは0か1になる.つまり表現したい数字は0から255まであり得る.

つまりパソコン内部のデータは1バイトの場合,a〜hの値が0か1か分かれば表せるということになる.

a b c d e f g h

1バイトのバイナリとは上記のように,どの「箱」に0か1が入っているかを表記したものである.例えば"2"を表したいときは

0 1 0 0 0 0 0 0

となる.


4バイト(単精度)と8バイト(倍精度)

今回の概論で,8バイトつまり倍精度の実数を使うようにしたのには訳がある.結局は表現できる数字が細かくなる.
上述したように1バイトでは256階調でしか数字を表現できない.4バイト,8バイトと上げていくと当然,数値を細かく表現できることになる.
例えば塩分 34.5689 (psu)という数字を合算していく場合,4バイトでは小数点以下の数値がうまく表現できず
丸め込み誤差というものが
生まれる.
冒頭の話に戻ると,32ビットOSから64ビットOSになると,表現できることや扱える仕事量が増える(多機能になる)ということ.


バイナリ画像とはなんぞや

さて今回の概論で扱うバイナリ画像は,海底地形図と海面水温図である.ここでは前者についてのみ説明する.
扱うのは2バイトInteger(整数型)の海底地形図である.サイズは421×361となっている.




1バイトの場合,1ピクセルの値が上で示したように8個の箱に入っている数値で表されている.
今回扱う,2バイトIntegerは正確には,「Short Integer」と呼ばれるもので,−32768〜32768の数値を表すことができる.
ちなみに「unsigned integer」は表現できる範囲が0〜65535=216階調となる.同じ整数でも,Short integerの場合は,
左端(ビッグエンディアン)もしくは右端(リトルエンディアン)の値を正か負かという表現に割り当てている.
エンディアンについては,最後のバイトオーダーのところに簡単に説明する.

2バイトの場合,1ピクセルの値が16個の箱に入っている数値で表されている.
今回の海底地形図のピクセル数は421×361であるので,「16個の箱の組み合わせ」が421×361(151981)個,横一列並んでいるというイメージ.


フォートランプログラムでこのデータを読む際には,バイナリのサイズを明示してやる必要がある.

     integer*2 bath(421,361) ! ← 宣言文

     open(10,file="./BATHY_421x361_4f.flat", access="direct",   ! ← OPEN文

&    form='unformatted', recl=421*361*2,status="old")

     read(10,rec=1) bath

     close(10)

宣言文でinteger*2 bath(421,361)としたのは,画像と同じようにデータを配置したいがためにやっている.
OPEN文内のreclとは record length(レコード長)のことで,データの長さ(サイズ)を示している.

ls -al BATHY_421x361_4f.flat

としてみよう.海底地形のファイルサイズ 303962(=421×361×2)がこのレコード長と合致しているはずである.
上にあるOPEN文は,「
421x361x2サイズで,フォーマット無しのバイナリファイル"BATHY_421x361_4f.flat"を開けますよ
ということを意味している.

次にREAD文で,421x361の2バイトInteger(整数型)変数に,海底地形データを入力している.rec=1とはレコード番号1ということを
意味している.今回のデータはパソコン内部では「一行のデータ(1レコード目しかない)」と認識されるのでrec=1にしている.

仮に,海底地形データ(1レコード目)の次に水温画像のバイナリがくっついている場合,水温画像のデータ読み出しは
read(10,
rec=2) 「任意の変数名」
となる.

混乱するかもしれないので簡単にまとめると,
今回扱う画像は一枚で,パソコン内部では
1)0か1の数字で表現されたバイナリデータである.
2)パソコン内部で扱われるときは,画像として認識できるような配置(2次元配列)になっているわけではなく,
  一行のデータで格納されているイメージで考えればよい.


バイトオーダー

ここは興味のある人へのお話.冒頭に出てきたように「左から順に」0か1の数値を格納する方式をビッグエンディアンという.
この方式はSUNのSPARC,IBMマシンなどで採用されている.一方で,Intel系,AMD系のCPUでは順列が逆の方式を採用しており,
リトルエンディアンと呼称される.前者は直感的に分かりやすい,後者はコンピュータにとって処理しやすい(http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%B3%E3%83%87%E3%82%A3%E3%82%A2%E3%83%B3).
ビッグエンディアンのバイナリを,エンディアン変換せずに,Intel系のCPUを搭載したマシンで処理すると,わけのわからん数値になるのは
容易に想像できるであろう.