はじめMath! Javaでコンピュータ数学

第8回 実数型のしくみ[前編]

この記事を読むのに必要な時間:およそ 3 分

IEEE754の内部

IEEE754形式の単精度は,符号部S(1ビット)・指数部E(8ビット)・仮数部M(23ビット),倍精度は符号部S(1ビット)・指数部E(11ビット)・仮数部M(52ビット)で表現されています。各部は図8.2のように構成されています※7)⁠各部の意味は表8.2の通りです。

図8.2 IEEE754 のビット構成

図8.2 IEEE754 のビット構成

表8.2 IEEE754各ビットの意味

名称意味
符号部0の時は正の数,1の時は負の数を表す。
指数部基数2を何乗するかを表す。
仮数部仮数から1引いたもの

指数部にはバイアス※8がかけられています。バイアス値は単精度のとき127,倍精度なら1023です。指数部には,表8.3に示す注意すべき値があります。0を0で割ろうとするとき,また,を求めようとすると演算結果はNaNになります。

表8.3 指数部の例外

指数部の値左の値をとるときの意味
255(単精度)
2047(倍精度)
仮数部が0以外の時はNaN(NaN; Not a Number,非数)を表す。
仮数部が0かつ符号部が0ならば正の無限大,符号部が1ならば負の無限大を表す。
0指数部,仮数部ともに0ならばその数は0を表す。

以上のことをまとめると,IEEE754形式で表現する浮動小数点数の実数Rの値は次の式で表せます。

Bはバイアス値です。前述のとおり,Rがfloat型ならB=127,double型ならB=1023です。

※7
整数型は最左に符号ビットが1ビット,残りのビットが数値を表しています。負数は2の補数で表現します。
※8
バイアスとは,値を底上げすること。ここでは,指数部の数値に127ほど足しておく,という意味です。IEEE754で指数部には符号をつけず,127をバイアスとする,と決めたからで,絶対的な根拠があるわけではありません。バイアスを用いず,指数部を符号付きの数値にしても良かったのです。しかし,浮動小数点数の表現方式として次に有名なIBM方式でも指数部にバイアスを用いていることから,計算効率等合理的な理由があるのでしょう。

10進数の数値をIEEE754単精度値に変換する

10進数の数値をIEEE754単精度の規格にそった16進数表示に変換する手順を示します。倍精度の場合は仮数部,指数部の桁数とバイアス値を読みかえるだけで手順に違いはありません。単精度での変換方法をしっかり納得しておけば,倍精度で変換練習する必要はないでしょう。

10進数数値のIEEE754単精度値への変換方法

例)-123.45をIEEE754単精度16進数表示に変換する。

(1)負の数なので符号部は1になる。

(2)絶対値の123.45を符号無し2進数に変換すると(111 1011.01 1100 1100 ・)Bになる。割り切れることなく(1100)Bが続く。(基数変換の手順については連載第6回を参照してください)

(3)符号無し2進数の左端の1の次に小数点を置く。ここでは小数点が左に6桁移動した。すなわち,(1.1110 1101 1100 1100 ・)B

(4)仮数部は(3)で出した小数点以下の値23ビット分となる。すなわち,(1110 1101 1100 1100 1100 110)Bとなる。23ビット目で切り捨てたため誤差が発生した。

(5)指数部の値は,⁠3)で出した小数点の移動量が左に6桁であるため,+6+127=133とする。133を2進数に変換して(10000101)B。⁠もし仮に小数点の移動量が右に6桁であった場合は,指数部は(-6)+127=121となる。)

(6)以上より,-123.45は(0xc2f6e666)Hとなる。

表8.4にint型とfloat型の内部表現を並べて示します。たとえ負数でなくて,同じ32ビットのデータ型でも,符号付きの整数型と,単精度IEEE754の型では,中身が別物であることがよく分かるでしょう。

表8.4 型による内部表現の違い

整数型の100
単精度IEEE754の100
(0x00000064)H
(0x42c80000)H

IEEE754単精度値を10進数値へ変換する

IEEE754単精度値を10進数値へ変換する手順を示します。部分の計算は筆算では大変ですので,電卓を使用しましょう。

IEEE754単精度値の10進数値への変換方法

単精度浮動小数点数値(0x40490e56)Hを例にとって,10進数値に変換する方法を示す。
2進数に変換

(0 x 4    0    4    9    0    e    5    6)H
( 0100 0000 0100 1001 0000 1110 0101 0110)B
符号部( 1bit) : (0)B
指数部( 8bit) : (100 0000 0)B = (128)D
仮数部(23bit) : (100 1001 0000 1110 0101 0110)B
                1   4  7      12    17   21
                                13    19   22
                                 14

符号部0より,正の数。(-1)0 = 1。

指数部が128だから,2128-127=21=2です。

仮数部は左からを表す。nは小数点以下第n位のこと。仮数部のビットが1になっている桁について全て合計すると仮数部の10進数値となる。

以上の結果をIEEE754の定義に従い計算すると,

画像

(0x40490e56)Hは小数点以下4桁までの円周率であることがわかった。

今回はここまで

次回は実数値を16進数で表示するプログラムを作ります。次に実数値を筆算と電卓で,10進数から16進数に変換してみます。

その逆に16進数で表示された実数値を,10進数に戻します。確認は自分で作成したプログラムで行います。この作業を通じて,浮動小数点数の仕組みと,長所・短所が体で理解できることでしょう。お楽しみに。

今回のまとめ

  • Java言語の内部では実数の表現方法としてIEEE754の浮動小数点数を使用している。
  • 浮動小数点数は近似表現なので,多くの場合で誤差を発生する。

著者プロフィール

平田敦(ひらたあつし)

地方都市の公立工業高等学校教諭。趣味はプログラミングと日本の端っこ踏破旅行。2010年のLotYはRuby。結城浩氏のような仕事をしたいと妄想する30代後半♂。