※「セキュリティ保護のため...」というメッセージが出る方・日本語が入力できない方へ
数の表現


元々「コンピュータ」は「計算機」であるから、数を扱うのがその本業である。そしてその当初は全ての数は2進数で処理されていたが後に他の形式も出てくる。

マイナスの数の表現

0と1しかない2進数のコンピュータの世界でどうやってマイナスを表すかという問題は初期にかなり議論された。幾つかの案の中から3つの方法が生き残った。

(1)絶対値法
符号のためのビットを1つ設けて、あとは絶対値で表す方法である。この方法では例えば8ビットのマシンでは先頭の1ビットを符号に使用し、残りの7ビットは数の絶対値を格納する。従って、例えば98 は 00110010 であるから -98 は 10110010 になる。

(2)1の補数
1の補数というのはマイナスの数を全てのビットを反転させて表現する方法である。例えば 98 は 00110010 だから、-98を1の補数で表現すると 11001101 になる。マイナスの数であるかどうかは先頭ビットで判定できる。

1の補数の欠点は0が 00000000 及び 11111111 という二通りの表現形式を持ってしまうことである。

(3)2の補数
2の補数とは1の補数で表された数に1を加えたものである。例えば 98 は 00110010 だから、-98を2の補数で表現すると 11001110 になる。マイナスの数であるかどうかはやはり先頭ビットで判定できる

この方法を取ると0が2通りに表現される問題は消滅する。0は00000000であり、11111111は -1 になる。2の補数の最大のメリットは足し算を行う時にプラスであるかマイナスであるかによって場合分けをせずに、全て同じロジックで処理できることにある。すなわちマイナスの数を2の補数で表現することによって計算機の演算回路が大幅に簡略化することができるのである。このため、マイナスの数は基本的には2の補数で表現することが少なくとも1970年頃までには常識となっていた。

10進数の表現

さて、コンピュータの内部では全てのデータを2進数で処理しておいて全然問題ないのであるが、その計算結果を人間が見る場合、また元になるデータを人間が入力する場合全て2進数でやるというのは大変である。そこで人間が分かりやすい10進数のデータも何とか処理できる必要性が出てきた。

このやり方は基本的に言って10進数の各桁を2進数で表現するためBCD(Binary coded Decimal,2進化10進数)と呼ばれる。2の4乗が16であるから10進数の各桁は4ビットあれば表現できる。このコード化の方法は初期の段階では様々な方法が提唱されたが結果的には一番自然な次のような方法が主流となった。

 0=0000 1=0001 2=0010 3=0011 4=0100
 5=0101 6=0110 7=0111 8=1000 9=1001

この場合、たとえば18桁の10進数は 18x4=72ビットあれば表現できることになる。この方式を現在パック10進数(packed decimal)と呼んでいる。

このパック10進数の問題点は各桁に4ビットしか使っていないため、後にコンピュータの基本となったバイトマシン、つまり8ビットを基本単位として処理するマシンにおいてデータの処理に煩わしさが出てきたことである。バイトマシンでは全て8ビット単位で処理したいものである。そこで、この数字の各桁をそのまま1バイトに割り当てる方式が誕生した。これをアンパック10進数(unpacked decimal)と呼ぶ。1バイトに割り付ける場合に4ビット余ってしまうので、下4ビットに数字を入れて上4ビットにはダミーのビット列を割り当てる。このダミーのビット列としてIBM社は 1111(F) を採用したがアメリカ標準規格は 0011(3) を採用した。前者は主として大型汎用機・オフコンで使用され、後者は主としてミニコン・パソコンで使用された。この問題は後で文字コードの所でまた触れる。

実数の表現

さて全ての数が整数であれば何の苦労もしなくてよいのだが、不幸にして数には小数というものが存在する。1.5 とか 3.14 とかいったものである。このような「実数」を表現する場合2通りのアプローチが存在する。

(1)仮想小数点方式
COBOLの世界では数は基本的に上述の10進数(BCD)で表現するが実数については仮想小数点というアプローチ用いる。これはつまり全ての数を整数で表現し、小数点は仮想的に考える。つまりデータ自体には書き込まないで、プログラムの解釈で処理するのである。たとえば、小数点以下2桁の数まで必要ということが分かっていたら、96を表現するときは 9600、1.5 なら 150、3.14 なら 314 というふうに書いておき、それを96.00、1.50、3.14 のことであると「思う」という考え方である。これは経理などの計算に置いて1円の計算誤差も許されないというCOBOLが処理する世界の事情がこういうやり方を要求したのである。

(2)浮動小数点方式
C(++),BASIC,FORTRAN,PASCALなどの世界では実数は一般に浮動小数点形式で表される。これは数を例えば 0.31428 x 2の12乗、などという形で表現する方法である。0.31428の部分は仮数部、12乗の部分指数部と呼ばれる。この具体的なやり方については後の各論を参照のこと。

卵の食べ方

一般にひとつの数を表すには複数のバイトが必要である。例えば短形式の整数(int2,short)の場合、-32768 〜 32767 の数を表すことができるがこの int2 を格納するのには32ビット=2バイトが必要である。これが標準整数(int4, long) の場合は 64ビット=4バイトになる。

このように複数のバイトを使って数を表現する場合、どちらからバイトを使用するかというので、リトルエンディアン(little endian)方式とビッグエンディアン(big endian)方式がある。たとえばint4の64ビットの数を格納する場合に、前者では先頭バイトに0-7ビット、次のバイトに8-15ビット、次のバイトに16-23ビット、最後のバイトに24-31ビットを格納するが、後者では先頭バイトが24-31ビット、次が16-23ビット、次が8-15ビット、最後が0-7ビットである。一般にインテル社のCPUはリトル・エンディアン方式、モトローラ社のCPUはビッグ・エンディアン方式を採用している。

リトル・エンディアン方式は、小さい数を小さいアドレスに書くべきだという考えから来ている。ビッグ・エンディアン方式は、数字は高位の数を左側に書くではないか、という考えから来ている。

この用語の出典はガリバー旅行記である。ガリバー旅行記で小人の国に行ったとき、二つの国が戦争を始めた原因が、卵を細い方から食べるか太い方から食べるかという問題であった。前者をリトル・エンディアン、後者をビッグ・エンディアンと言う。

実際の具体的表現方法

【固定小数点数】

固定小数点形式は数をそのまま2進数で表現したものである。整数型とも呼ばれる。プログラム内では符号付き(signed)と符号無し(unsigned)の区別があるが、データとしては区別はなく、全て正数として処理するか、最上位ビットが1のものを2の補数で表現された負数とみなすかの違いだけである。

int1 (char)型 or
-128〜+1270〜255
int2 (short)型 or
-32768〜+327670〜65535
int4 (long)型 or
-2,147,483,648〜+2,147,483,6470〜4,294,967,295
int8 型 or
-9,223,372,036,854,775,808〜
+9,223,372,036,854,775,807
0〜
18,446,744,073,709,551,615

【浮動小数点数】

浮動小数点数は数を仮数部と指数部とに分けてa×2の形で表現したものである。実数型とも呼ばれる。これには各社ごとの色々なフォーマットがあったと思われるが、データ交換などに使用されるものは主としてMicrosoft形式とIEEE形式である。前者は機能の低いマシンでも処理プログラムを比較的簡単に作れる構造になっているためパソコンBASIC文化の中で多用された。しかし現在はIEEE規格のものが主流であり、Microsoft製品でも最近のソフトは基本的にIEEE形式を使用している。

real4(float)-MS 指数部8bit,仮数部23bit。
精度6.9桁。最大絶対値38.2桁。
仮数部をf2,...,f24、E=1〜255として
data = (-1)S×(1/2+Σ(fn/2n)×2E-128  (Σ:n=2-24)
real4(float)-IEEE 指数部8bit,仮数部23bit。
精度6.9桁。最大絶対値38.8桁。
仮数部をf1,...,f23、E=1〜255として
data = (-1)S×(1+Σ(fn/2n)×2E-127  (Σ:n=1-23)
real8(double)-MS 指数部8bit,仮数部55bit。
精度16.5桁。最大絶対値38.2桁。
仮数部をf2,...,f56、E=1〜255として
data = (-1)S×(1/2+Σ(fn/2n)×2E-128  (Σ:n=2-56)
real8(double)-IEEE 指数部11bit,仮数部52bit。
精度15.6桁。最大絶対値308.5桁。
仮数部をf1,...,f52、E=1〜2047として
data = (-1)S×(1+Σ(fn/2n)×2E-1023  (Σ:n=1-52)

【10進数】

10進数は数を10進数のまま表現したもので、10進数の各桁を2進数数桁で表現することからBCD(Binary coded decimal,2進化10進数)と呼ばれる。これには1桁に4bit割り当てるパック形式(packed form)と8bitつまり1バイト割り当てるアンパック形式(unpacked form)がある。又符号付きと符号無しの形式がある。

アンパック符号無し
アンパック符号付き
パック符号付き
パック符号無し
ここでZと書いたものは一般にゾーン(zone)と呼ばれるが要するにダミーである。アンパック形式の書き方は数を文字と同等に扱おうという考え方になっており、通常の文字のコードの一部になるように、このゾーンを定めている。この値はIBMが定めたEBCDIC規格では1111(F)であるが、アメリカ標準のASCII規格では0011(3)である。また符号付きアンパックの場合最後の桁の上4bitに符号が格納され、その値はEBCDICではプラスの場合1100(C)、マイナスの場合1101(D)である。ASCII(というかMicroFocus-COBOL方式)ではプラスの場合0011(3)、マイナスの場合0111(7)である。

EBCDIC規格はIBMの大型コンピュータやオフコンなどで使用され、ASCII規格はパソコンやミニコンで使用された。しかし現在ほとんどのコンピュータがパソコン・ミニコン系になってしまった結果、ASCII規格が主流になったが、依然として大きなシステムのファイルはEBCDICで書き込まれているものが多いと推定される。



(C)copyright ffortune.net 1995-2007 produced by ffortune and Lumi.
お問い合わせはこちらから