前回はコンピュータにおける整数の扱いについて学びました。今回はさらに奥に入り,小数について調べてみましょう。コンピュータ上の小数は整数以上に複雑な謎に満ちているのです。

 小学校に入学したばかりのころ,算数の時間に学んだ「数」は整数,それも正の数だけでした。しかし,学年が進むと1よりも小さい数を取り扱う小数が登場します。0.2や1.5ですね。高等学校では数の範囲が広がり,小数を実数の一種として考えます。

コンピュータにおける小数の扱い

 コンピュータでも小数を取り扱います。プログラムで小数点を含む数を書くと小数を表します。

puts 0.2

 このRubyのプログラムは0.2という数を1つ用意し,出力します。Rubyの場合,すべてのデータはオブジェクトですから小数もオブジェクトです。小数を表現するオブジェクトのクラスをFloatと呼びます。数なのにfloat(浮く,浮かぶ)とはおかしな名前ですが,これはコンピュータ上の小数が「浮動小数点数(floating point number)」と呼ばれることに由来しています。

固定小数点数は使いにくい

 浮動小数点数とは「小数点」の位置が動くことから名前が付いています。コンピュータでの数の表現方法と,密接に関係しています。

 コンピュータは元々,整数,それもビットの並びのみを処理します。ですから,何らかの方法で小数点以下の位を持つ数をビット列に書き換える(エンコードする)必要があります。

 小数をビット列にエンコードする方法はいくつか考えられます。代表的な方法は次の2つです。

●小数にげたを履かせて整数化する
●科学的記法を使って表現する

 「げたを履かせる」とはすべての小数を例えば100倍*1して整数化し,小数点以下を表現する方法です。100倍することで小数点以下2けたを表現できます。このような小数の表現方法を固定小数点数(fixed point number)と呼びます。有効数字が小数点以下何けたかはっきり分かっているデータを扱うプログラムで時々用いられます。

 この方法は小数を整数演算を用いて計算することから,処理が高速になるというメリットがあります。一方,デメリットもあります。仮に10進で2けたのげたを履かせた表現を用いると1は1.00となり,小数点以下の2けた分が無駄になります。結果として次のような制約が生まれてしまいます。

●そのビット幅で本来表現できる情報よりも小さい値しか表現できない(整数部の無駄)
●10進2けたの場合,0.01単位の小数しか表現できない(小数部の制限)

 このような理由から固定少数点数はあまり広くは使われていません。

科学的記法にも問題がある

 コンピュータで広く用いられている小数の表現方法は,科学的記法です。科学的記法とは有効数字と指数の組み合わせによって小数(実数)を表現するもので次のように書きます。

2.5 × 104

 これで,2万5000を意味します。

 ただし,コンピュータでは10進ではなく,2進数で数を表現するため,実際にはデータとして内部に2.5と104が記録されているわけではありません。ビット列への変換が必要です。

 ビット列への変換方法は何種類かありますが,以下では広く用いられているIEEE754方式を紹介します。

 IEEE754方式では小数を表現するために単精度(float)で32ビット,倍精度(double)で64ビットの領域を使います。多くのCPUでは浮動小数点数の計算を内部的にdouble*2で行いますから(floatの場合,doubleで計算した結果をfloatに変換する),以下ではdoubleのみを説明します。

 doubleを表現する64ビットのビット列は図1のよう区割りされています。

± f × 2e


という形式を使います。

図1●IEEE754方式によるdouble型の浮動小数点数の内部表現
図1●IEEE754方式によるdouble型の浮動小数点数の内部表現

 fに相当する部分を仮数部(mantissa),eに相当する部分を指数部(exponent)と呼びます。doubleでは指数部eが11ビットあるため+1023から-1022までを表現できます。2の1023乗まで表現できるわけですね。

 一方,仮数部fは52ビットあります。IEEE754表現では「仮数部の先頭ビットは常に1に正規化*3される」と決まっているので,先頭1ビットは常に省略されており*4,実質有効数字は53ビット分あります。

*3

例えば48という数を表現する際,3×24と表せる。
正規化するとは1.5×25のように仮数部が1以上2未満に
収まるように数の表現を変形することを言う。