単精度浮動小数点数

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索

情報処理において、単精度浮動小数点数 (Single precision floating point number) は、コンピュータの数値表現の一種である。

浮動小数点形式の標準であるIEEE 754では、単精度は32ビット(4オクテット)、倍精度64ビット(8オクテット)である。IEEE 754-2008 では単精度の形式は正式には binary32 と呼ばれている。「単」や「倍」という表現は32ビットを1ワードとする32ビットアーキテクチャを基にしている。

単精度浮動小数点数は、同じ幅の固定小数点数に比べてより広範囲な数値を表せるようになっているが、同時に精度を犠牲にしている。

C言語C++C#JavaHaskellでは単精度のデータ型を float と呼び[1]PascalMATLABなどでは single と呼ぶ。3.2以前のOctaveでは single という名前だが倍精度である。Pythonfloat も倍精度である。

IEEE 754 での単精度浮動小数点数の形式: binary32[編集]

IEEE 754 での binary32 の定義は次の通りである。

  • 符号ビット: 1ビット
  • 指数部の幅: 8ビット
  • 仮数部の幅=精度: 24ビット(実際に現れるのは23ビット)

符号ビットは表現する数値の符号(正負)を示し、仮数の符号でもある。指数は8ビットの符号付整数であり、-128 から 127 までの値をとる。あるいは符号なし整数と解釈すれば 0 から 255 までの値をとる。IEEE 754 の binary32 フォーマットではバイアス付きの値として解釈され、指数部が127のとき実際には0を表している。

指数部が全て 0 でない限り、この形式では「暗黙の整数ビット」を 1 とみなす。従って小数部の23ビットだけがメモリフォーマット上に出現する。従って十進に換算したとき表現できる桁数は log10(224) ≈ 7.225 桁となる。ビットのレイアウトは以下のようになる。

Float example.svg

符号ビットを sign、バイアスつきの指数部を e、23ビットの仮数部の各ビットを b-n とすると、32ビットの binary32 フォーマットで表される数値は (-1)^{sign}(1.b_{-1}b_{-2}...b_{-23})_2 \times 2^{e-127} となり、より正確に表現すると  value = (-1)^{sign}(1 + \sum_{i=1}^{23} \ b_{i}2^{-i} )\times 2^{(e-127)} となる。

指数部の符号化方式[編集]

単精度バイナリ浮動小数点数の指数部はオフセット表現を使って符号化されており、指数値がゼロのときのオフセット値(バイアス値)は127である。

  • Emin = 01H−7FH = −126
  • Emax = FEH−7FH = 127
  • 指数部バイアス = 7FH = 127

指数部バイアスは、エクセスNとも言う。詳しくは符号付数値表現を参照されたい。真の指数値は、指数部の値から指数部バイアスを引いた値となる。

00H と FFH は予約された指数値である。

指数部 仮数部がゼロの場合 仮数部がゼロでない場合
00H 0, −0 非正規化数 (−1)signbits×2−126× 0.significandbits
01H, ..., FEH 正規化数 (−1)signbits×2exponentbits−127× 1.significandbits
FFH ±無限 NaN (quiet, signalling)

従って、全てのビットパターンが符号として意味がある。正の最小値(非正規化数)は 2−149 ≈ 1.4 × 10−45 である。正の正規化数の最小値は 2−126 ≈ 1.18 × 10−38 である。表現可能な最大値は (2−2−23) × 2127 ≈ 3.4 × 1038 である。

十進表現から binary32 フォーマットへの変換[編集]

IEEE754 では実数値から対応する binary32 フォーマットへの変換を丸めも含めて厳密に定めている。

ここでは十進の実数値から IEEE 754 binary32 フォーマットへの変換は大まかに次のようになる。

  • 実数値を 12.375 のように整数部と小数部で表すものとする。
  • 整数部を二進法で表現したものに変換する。
  • 小数部を以下に示す技法で変換する。
  • 2つの変換結果を組み合わせ、さらに変換を加えて最終的な表現を得る。

小数部の変換:

12.375 の小数部 0.375 を例とする。これを二進の小数に変換するため、小数部に2をかけて整数部をとり、さらに2をかけて整数部をとるというように繰り返していき、小数部がゼロになるか精度の上限である二進23桁になるまで続ける。

0.375 x 2 = 0.750 = 0 + 0.750 ⇒ b−1 = 0 となるので、二進での小数部の一桁目はゼロとなる。そこでさらに 0.750 に2をかける。

0.750 x 2 = 1.500 = 1 + 0.500 ⇒ b−2 = 1

0.500 x 2 = 1.000 = 1 + 0.000 ⇒ b−3 = 1 となり、小数部が 0.000 となったのでここで変換は停止する。

これで (0.375)10 は正確に二進で (0.011)2 で表されることがわかった。十進で有限桁数の小数が必ず二進で有限桁で表せるわけではない。例えば、十進の 0.1 は二進では正確に表現できないため近似値を用いることになる。

したがって、(12.375)10 = (12)10 + (0.375)10 = (1100)2 + (0.011)2 = (1100.011)2 となる。

IEEE 754 binary32 フォーマットでは、値を  (1.x_1x_2...x_{23})_2 \times 2^{e} という形式で表現しなければならないので、1100.011 をシフトして整数部が一桁になるようにしなければならない。この例では3桁シフトするので  (1.100011)_2 \times 2^{3} となる。

最終的に  (12.375)_{10} =(1.100011)_2 \times 2^{3} となる。

この結果から次が得られる。

  • 指数部は 3 となる(バイアスを加えるので実際は 130 = 1000 0010 となる)。
  • 仮数部は 100011 となる(小数点より右側だけを仮数とする)。

したがって、IEEE 754 binary32 フォーマットで 12.375 を表すと 0-10000010-10001100000000000000000 = 41460000H となる。

注: 68.123 を IEEE 754 binary32 フォーマットで表す場合を考えてみよう。上述の技法を適用すると 42883EF9H というビット列が得られ、最後の4ビットは 1001 となる。しかし、IEEE 754 のデフォルトの丸め方式により最終的に 42883EFAH となり、最後の4ビットは 1010 となる。

例: 十進の1を変換すると  (1)_{10} =(1.0)_2 \times 2^{0} となる。ここから次のことが導かれる。

  • 指数は 0 である(バイアスを加えるので 127 = 0111 1111 となる)。
  • 仮数は 0 である(小数点より右側はゼロなので仮数部のビット列は全てゼロになる)。

従って実数 1 を IEEE 754 binary32 フォーマットで表すと 0-01111111-00000000000000000000000 = 3f800000H となる。

例: 0.25 を変換すると、 (0.25)_{10} =(1.0)_2 \times 2^{-2} となる。ここから次のことが導かれる。

  • 指数は -2 である(バイアスを加えるので 127+(−2)= 125 = 0111 1101 となる)。
  • 仮数は 0 である(小数点より右側はゼロなので仮数部のビット列は全てゼロになる)。

従って実数 0.25 を IEEE 754 binary32 フォーマットで表すと 0-01111101-00000000000000000000000 = 3e800000H となる。

例: 0.375 を変換すると、 0.375 = {(1.1)_2}\times 2^{-2} となる。ここから次のことが導かれる。

  • 指数は -2 である(バイアスを加えるので 127+(−2)= 125 = 0111 1101 となる)。
  • 仮数は 1 である(1.1 の小数点より右側は 1 = x1 のみである)。

従って実数 0.375 を IEEE 754 binary32 フォーマットで表すと 0-01111101-10000000000000000000000 = 3ec00000H となる。

単精度浮動小数点数の例[編集]

浮動小数点数値のビット列を十六進法で表した例を以下に示す。これには符号、バイアスを加えた指数値、仮数値が含まれている。

 3f80 0000   = 1
 c000 0000   = -2

 7f7f ffff   ≒ 3.4028234 x 1038  (単精度浮動小数点数の正の最大値)

 0000 0000   = 0
 8000 0000   = -0

 7f80 0000   = 正の無限大
 ff80 0000   = 負の無限大

 3eaa aaab   ≒ 1/3

1/3 は倍精度とは異なり、切り上げられる。これは仮数部のビット数が偶数であるため、丸める桁位置以降が 1010... となってその桁位置で 1/2 より大きくなるためである。

単精度バイナリ形式から十進への変換[編集]

16進の値 41c80000 を例として変換を行う。これを二進で表すと次のようになる。

41c8 000016 = 0100 0001 1100 1000 0000 0000 0000 00002

これを、符号ビット、指数部、仮数部の3つに分割する。

符号ビット: 0
指数部: 1000 00112 = 8316 = 131
仮数部: 100 1000 0000 0000 0000 00002 = 48000016

ここで仮数部に暗黙の整数ビットを加える。

仮数: 1100 1000 0000 0000 0000 00002 = C8000016

指数部の値から127を引いて実際の指数値を得る。

指数部の値: 8316 = 131
本来の指数: 131 − 127 = 4

24ビットの仮数は最上位ビットが1に対応し、次の桁が0.5、その次が0.25というように、前の桁の1/2に対応している。

bit 23 = 1
bit 22 = 0.5
bit 21 = 0.25
bit 20 = 0.125
bit 19 = 0.0625
.
.
bit  0 = 0.00000011920928955078125

この例では、仮数で立っているビットは bit 23、bit 22、bit 19 の3ビットだけであり、上記の対応する値を加算することで十進での仮数が得られる。

本来の仮数: 1 + 0.5 + 0.0625 = 1.5625 = C80000/223

基数 2 を指数値でべき乗したものを仮数にかけると本来の値が得られる。

1.5625 × 24 = 25

従って

41c8 0000   = 25

となる。これは次の式と等価である。

n = (-1)^s \times
           (m2^{-23})\times
           2^{x - 127}

ここで s は符号ビット、x は指数部、m は仮数を基数10で表したものである。

MSXの場合[編集]

MSX-BASICの演算ルーチンMATHPACKの場合、同様に4バイトで表すが、IEEE 754とは異なり

  • s(符号ビット): 1
  • y(指数部の幅): 7
  • x(仮数部の幅=精度): 24
 syyy yyyy xxxx xxxx xxxx xxxx xxxx xxxx

であり、指数部をバイナリ、仮数部をBCDで表現する。 そのため、有効数字は正確に10進で6桁で、指数は±63乗である。

ちなみに、同時期の8ビットパソコンのBASICでは、多くがBCDではなく2進での演算であった。

脚注・出典[編集]

関連項目[編集]

外部リンク[編集]