矢沢 久雄

 今回は,小数点数を表す方法を説明します。コンピュータは,内部的に2進数を使ってデータを取り扱っているのですから,小数点数も2進数で表します。ただし,2進数では0と1だけを使いますから,小数点のドット(.)を表す手段がありません。したがって,何らかの工夫をして小数点数を表さなければならないのです。

2進数の小数点数を10進数に変換する方法

 はじめに,2進数の小数点数を10進数に変換する方法を説明しておきます。これを知らない人が,意外と多いようです(本当なんですよ!)。ここでは,コンピュータのデータ表現ではなく,あくまで紙の上の算数として2進数の小数点数を考えます。したがって,ドットを使って小数点位置を表します。

 2進数で表された0110.1010という小数点数を10進数に変換してみましょう。小数点以上の部分は,すぐに変換できますね。それぞれのけたの値に重みを掛けた結果を足せばよいのです。0×23+1×22+1×21+0×20=6となります。それでは,小数点以下はどうなるのでしょう。やはり,それぞれのけたの値に重みを掛けた結果を足せばよいのです。

図1●小数点以下の重みは,基数のマイナス乗になる
 2進数の小数点以下の重みが,いくつになるかわかりますか? こういうことは,皆さんが使い慣れた10進数を例にして考えると,ピンとくるものです。10進数では,小数点以下1けた目の重みが0.1=10-1であり,小数点以下2けた目の重みが0.01=10-2,…となります。整数部の1けた目の重みが100なのですから,小数点以下の重みが10-1,10-2,…となるのは,理にかなっています。これは,2進数でも同様です。小数点以下1けた目の重みが2-1であり,小数点以下2けた目の重みが2-2,・・・となります。念のため,説明しておきますが,2-1=1/21,2-2=1/22ですよ(図1[拡大表示])。

 ここまで説明すれば,0110.1010という小数点数を10進数に変換できますね。整数部は,先ほど求めたとおり6です。小数点以下の0.1010だけ変換すると1×2-1+0×2-2+1×2-3+0×2-4=0.5+0.125=0.625となります。したがって,2進数の0110.1010は,10進数の6+0.625=6.625です。簡単でしょう!

浮動小数点形式

 紙の上に表された0110.1010という2進数の小数点数を,コンピュータで取り扱うデータとして表現するには,どうしたらよいでしょう。「8ビットを上位4ビットと下位4ビットに分け,その間に小数点のドットがあると仮定する」というのも1つの方法でしょう。ところが,実際には,このような方法は使われません。なぜなら,表現できる値の範囲が小さく,かつ不連続なものとなってしまうからです。

 符号ビットを考えずに,2進数の0000.0000~1111.1111が10進数でいくつになるか調べてみましょう。小数点以上の0000~1111の部分は,0~15の連続した値になりますが,小数点以下の0.0000~0.1111の部分は,0~0.9375の範囲の不連続な値になってしまいます。0~15.9375までの値を表せますが,15.9375の1つ前の値は15.875です。これでは,実用的でないですね(表1)。

2進数0.0000.0010.00100.00110.01000.01010.01100.0111
10進数00.06250.1250.18750.250.31250.3750.4375
2進数0.10000.10010.10100.10110.11000.11010.11100.1111
10進数0.50.56250.6250.6875 0.750.81250.8750.9375
表1●2進数の0.0000~0.1111で表せる値は,10進数では不連続になる

図2●浮動小数点数形式で表された小数点数の例
 コンピュータで小数点数を表現する場合には,「浮動小数点数形式」を使うのが一般的です。浮動小数点数形式は,小数点数を「符号」,「指数部」,及び「仮数部」の3つで表します。ここでも,まず10進数で具体例を示しましょう。例えば,0.0123を浮動小数点数形式で表すと,図2のようになります。

 図2の中には,「基数」というものも登場していますが,人間の世界の基数は10で,コンピュータの世界の基数は2に決まっているので,実際のデータの中には,基数を表す部分は不要です。仮数部は,例えば「整数部を0とし,小数点以下1けた目を0でない値とする」というような約束(これを「正規表現」と呼びます)で表すので,実際のデータの中には,小数点を表すドットは不要です。指数部は,「イクセス表現」で表すので,実際のデータの中には,指数部の符号を表す部分は不要です。イクセス表現とは,指数部で0~100までの値を表せるなら,その中央の50を0とみなし,0が-50を表し,100が50を表すとみなす手法です。

 浮動小数点形式の「浮動」の意味も説明しておきましょう。0.0123,0.123,1.23という3つの10進数があったとします。これらの表現は,固定小数点数形式です。小数点のドットが,実際の値の小数点位置にバッチリ固定されているからです。ここで,先ほどの「整数部を0とし,小数点以下1けた目を0でない値とする」という約束で,それぞれの数値を表してみると,0.123×10-1,0.123×100,0.123×101となります。固定小数点数形式の表現と比べると,小数点数の位置が移動(浮動)していることが分かるでしょう。だから浮動小数点形式と呼ぶのです。

単精度浮動小数点数形式と倍精度浮動小数点数形式

図3●浮動小数点数形式の表現方法
 それでは,2進数で浮動小数点数形式のデータを表現する方法を説明しましょう。浮動小数点数形式には,小数点数の全体を何ビットで表すかによって,2つの形式があります。32ビットの「単精度浮動小数点数形式」と,64ビットの「倍精度浮動小数点数形式」です。これら2つの形式には,表現できる値の範囲に違いがあります。もちろん,ビット数の多い倍精度浮動小数点数形式の方が,単精度浮動小数点数形式より表現できる値の範囲が広くなります。図3[拡大表示]は,Visual BasicやVisual C++などWindows上の開発ツールで採用されているIEEE(Institute of Electrical and Electronics Engineers,米国電子技術者協会,アイ・トリプル・イー)の数値規格に準拠した浮動小数点数形式の表現方法です。

 符号が0なら正の値で,1なら負の値を意味します。仮数部は,小数点以上1けた目の値を1にしてから,その1を省略し,小数点以下だけを格納する正規表現にします(1ビットだけ節約するためです)。指数部は,倍精度浮動小数点数形式なら01111111111(10進数の1023)を0とみなすイクセス表現で,単精度浮動小数点数形式なら01111111(10進数の127)0とみなすイクセス表現で表します。

 具体例を示しましょう。単精度浮動小数点形式で,10進数の0.75という小数点数を表すと0-01111110-10000000000000000000000となります(ハイフンは,符号,指数部,仮数部の区切りを表すために挿入しました)。0.75は,正の値ですから符号は0です。指数部の01111110は,01111111を0とみなすイクセス表現ですから,-1です。仮数部の10000000000000000000000は,小数点以上1けた目の値を1として,その小数点以下だけを表しているのですから,1.1です(省略された1を戻しました)。基数は,2進数だから2に決まっています。したがって,0-01111110-10000000000000000000000=+1.1×2-1=1×20+1×2-1×2-1=+1.5×2-1=+0.75となります。バッチリ合ってますね!

ゾーン10進数形式とパック10進数形式

 コンピュータで使われる数値を表すデータ表現には,BCD(Binary Coded Decimal,2進化10進数)と呼ばれるものもあります。BCDは,昔ながらの大型コンピュータでよく使われます。プログラミング言語では,COBOLがBCDを使うようになっています。BCDには,「ゾーン10進数形式」と「パック10進数形式」の2種類があります。

図4●ゾーン10進数形式のデータ表現
 ゾーン10進数形式は,数字の文字コードで10進数の0~9の数値を表してしまうものです。多くの大型コンピュータで使われているJISコードでは,0~9が1バイト(=8ビット)の2進数00110000~00111001で表されます。これをそのまま使って,1バイトで1けたの数値を表します。符号は,最下位けたを表すバイトの上位4ビットで表します。0011がプラスを表し,0111がマイナスを表します。例えば,-1234という4けたの10進数は,図4[拡大表示]のように表せます。

 ゾーン10進数が便利なのは,キーボードなどの入力装置や,ディスプレイなどの出力装置で使われる文字コードを,そのまま使えるということです。そのため,プログラムの作成が容易です。人間の目にも,10進数に見えます。逆に,ゾーン10進数の問題点は,データを表すのに多くのビットが必要だということです。1けたのために8ビットを使うのですから,もったいないような気がしますね。

図5●パック10進数形式のデータ表現
 ゾーン10進数形式を小さくパックしたものが,パック10進数形式です。パック10進数形式では,4ビットの0000~1001を使って10進数の1けたを表します。したがって,1バイトで,2けたの10進数を表せることになります。符号は,最下位バイトの下位4ビットで表します。0011がプラスを表し,0111がマイナスを表すのは,ゾーン10進数形式と同じです。例えば,-1234という4けたの10進数は,図5[拡大表示]のように表せます。最上位バイトの上位4ビットは未使用なので,0000とします。ゾーン10進数形式で4バイト必要だったデータが,パック10進数形式では3バイトで表せていますね。ただし,ゾーン10進数形式のわかりやすさは,失われています。

 そもそも,BCDとは,4ビットで10進数の1けたを表すことを意味します。上位4ビットを0011にすれば,上位と下位を合わせた1バイトで,文字コードを表せます。上位4ビットの0011の部分を「ゾーン」と呼ぶのです。使用する文字コード体系が変われば,ゾーンの値も異なります。例えば,IBMが定めたEBCDICコードを使う場合には,ゾーンの値が1111になります。EBCDICコードでは,0~9の数字が11110000~11111001に割り当てられているからです。

 ところで,ゾーン10進数形式でもパック10進数形式でも,小数点数は表せません。小数点を表す手段が定められていないからです。それでは,BCDでは,小数点数の計算ができないのでしょうか? 実は,BCDで小数点数の計算が必要な場合には,プログラマの判断で,整数のどこかに小数点のドットがあると仮定して計算するようにしているのです。例えば,小数点以下2けたの計算が行ないたいなら,計算したい値を100倍して計算します。1.23+4.56を計算するなら,123+456=579を求め,結果を画面に表示するときに,5と79の間に小数点のドットを付加するのです。この方法を「仮想小数点方式」と呼ぶことがあります。

 今回は,浮動小数点数形式やBCDの説明をしましたが,コンピュータを使う人は,なんたって2進数に強くなければなりません。そこで,次回は,もっともっと2進数に慣れ親しんでいただくために,論理演算の説明をします。TrueとFalseだけのデータ表現の世界です。お楽しみに!