浮動小数点数

出典: フリー百科事典『ウィキペディア(Wikipedia)』

これはこのページの過去の版です。EmausBot (会話 | 投稿記録) による 2012年5月12日 (土) 10:45個人設定で未設定ならUTC)時点の版 (r2.7.3) (ロボットによる 変更: tr:Kayan nokta)であり、現在の版とは大きく異なる場合があります。

浮動小数点数(ふどうしょうすうてんすう)は、浮動小数点方式によるのことで、もっぱらコンピュータの数値表現において、それぞれ固定長の仮数部と指数部を持つ、数値の表現法により表現された数である。

概要

指数表現によって可能な十分に広い絶対値の範囲内において、仮数部の桁数に依って常に一定の範囲内の相対誤差で任意の実数を近似できるという特性がある。そのため、極端な数を扱う分野(科学計算など)で多く用いられている。また、プログラミング言語のほとんどが対応しているということもあり、小数の表現方法としては最も普及している。

整数演算と同じ操作で処理が済む固定小数点と違い、通常の整数演算命令を使って実装すると多くの命令が必要であるので、ハードウェアで実装したFPUなどのコプロセッサが用いられる場合が多く、現代のPC用のマイクロプロセッサなどでは内蔵している。

なお、この記事では固定精度の浮動小数点数のみ扱う。任意精度の浮動小数点については任意精度演算を参照のこと。

浮動小数点数の構造

浮動小数点数では次のデータで数値を表現する。

  • 仮数
    • (仮数の)符号
    • (値が非0の場合、1以上で基数未満の、または、1以下の)仮数の絶対値
  • 基数(1より大きい整数)
  • 指数(符号付き整数)

現在広く使われている表現方法ではいずれも基数を固定しており、明示的に符号化しないため、実際に符号化されるのは、次の3つである。

  • 符号部(1ビット
  • 仮数部(符号なし整数)
  • 指数部(符号付き整数)

浮動小数点数では、数値の絶対値は(仮数部)×(基数)(指数部)となる。たとえば、0.5を浮動小数点数で表すと、基数が10の場合は5.0×10-1(5.0e-1)、基数が2の場合は1.0×2-1となる。

2進法で正規化をすると、最上位ビットは常に1になるので、これを表さず常に1があるものとみなす省略が可能で、省略した表現をケチ表現などと言う。この省略を使うと、仮数部に割り当てたビット数がnであれば、有効桁数はn+1となる。

0を表す場合は符号部、仮数部、指数部のすべてのビットを0とすると都合が良いことからそのようにされることが多い。またその場合は+0.0で、浮動小数点では他に符号部が負をあらわし他が0の-0.0という0もあることがある。たとえば正の数を負の無限大で割ったり、負の数を正の無限大で割ったりすると-0.0になる。

浮動小数点数のフォーマット

主要な浮動小数点数のフォーマットには、以下がある。

  • IEEE方式(IEEE 754。最も広く採用されている標準規格)
  • IBM方式(エクセス64。IBMのメインフレームで使われていて、基数を16で表現する方式)

それぞれ32ビット表現(単精度)と64ビット表現(倍精度)とがある。 また、x86のFPUは内部表現に80ビット(拡張倍精度)表現を使っている。

IEEE方式(IEEE 754 形式)

単精度浮動小数点数型式
sign:符号部、exponent:指数部、fraction:仮数部
倍精度浮動小数点数型式

IEEE 754 形式の単精度浮動小数点数では、符号部 1 ビット ・ 指数部 8 ビット ・ 仮数部 23 ビット、倍精度では、符号部 1 ビット ・ 指数部 11 ビット ・ 仮数部 52 ビットで表現されている。各部は次のように定義されている。

  • 符号部は、 0 を正、1 を負とする
  • 仮数部は、整数部分が 1 であるような2進小数の小数部分を表す
  • 指数部は、符号なし2進整数とし、単精度では 127、倍精度では 1023 をバイアス(ゲタ履きともいう)した値で表す

つまり、IEEE 754 形式で表現する値は

単精度の場合: (-1) 符号部×2指数部 ‐127 ×(1+仮数部)
倍精度の場合: (-1) 符号部×2指数部 ‐1023×(1+仮数部)

である。

ただし、IEEE 754 形式の指数部は複雑で、以下のような役割も持つ。

  • 通常の浮動小数点数(正規化数)を表現するのは、指数部が単精度で 254 ~ 1(127 ~ -126)、倍精度で 2046 ~ 1(1023 ~ -1022)の範囲のときである
  • 指数部が、単精度の場合 255(128)、倍精度の場合 2047(1024)のとき:
仮数部が 0 以外の場合は、非数(NaN; Not a Number)を表す
仮数部が 0 の場合は、符号部が 0 のときは正の無限大、符号部が 1 のときは負の無限大を表す
  • 指数部が 0(単精度の場合 -127、倍精度の場合 -1023)のとき:
非正規化数
  • 指数部、仮数部ともに 0 のときは ±0 を表す

0 を 0 で割ろうとすると NaN になる。また、 も、求めるとNaNになる。

IEEE 754 で表現するまでの過程

2.5を例にとると、

  • 仮数の符号は、+
  • 仮数の絶対値は、2.5
  • IEEE 754の基数は、2で固定(簡単のため、以下では省略)
  • 指数は、0

であることから、まず次のように考える。

(-1)0×2.5×20

仮数部は1未満でなければならないため、仮数の値2.5を(この例では右へ)シフトし正規化する。基数は2、コンピュータの内部表現は2進数であるため、シフト量は1ビットである。さらに、右シフトして12になったことを相殺するため、指数に1を加える(もし左シフトなら、指数から1を引く)。 値をシフトすることで表現範囲を広げ、丸め誤差を少なくなるようにしている。この操作を正規化という。正規化は基数の±1乗を繰り返し求めればよい。

このままでは (-1)0×1.25×21 となり、仮数の絶対値は1未満ではないが、仮数部は 仮数 - 1 と決められているため、次のようになる。

(-1)0×(1 + 0.25)×21
  • 符号部は、0
  • 仮数部は、0.25
  • 指数は、1

指数部は、指数に127をバイアスすることが決まっているため

(-1)0×(1 + 0.25)×2(128 - 127)
  • 符号部は、0
  • 仮数部は、0.25
  • 指数部は、128

実際には2進数で表現されているので、2進数に直す。

  • 符号部(1ビット):+→0
  • 仮数部(23ビット):0.25→.01000000000000000000000
  • 指数部(8ビット):128→10000000

浮動小数点は、最上位ビットから符号部、指数部、仮数部の順に符号化するため

2進値:0 10000000 01000000000000000000000、16進値:40200000

IBM方式(エクセス64 形式)

エクセス64は、IBMがSystem/360で導入し、以後の同社のメインフレームで使われた方式である。指数部が2のべき乗ではなく16のべき乗を表すという特徴がある。この方式は、より大きな範囲を少ないビット数の指数部で表すことができ、そのぶんのビットを仮数部の桁数に使うことで精度も確保できるように一見思える。しかし、仮数部にケチ表現を使うことができず、さらに指数部の変化の前後で、仮数部のLSBが表現する値の刻み幅が16倍変化するため、2べきの場合に比べ最悪の場合の精度が2進で3桁ぶん損なわれるため、大成功と一般に評されるSystem/360において、まずかった点として挙げられる設計のひとつである。

特に単精度において、前世代機のIBM 7094(全部で36ビット)よりも桁数を減らした(32ビット)こととあいまって大きく精度がそこなわれた。その他にも問題があり、ユーザグループであるSHAREから改善提案が出され、その多くを受け入れて多大なコストのかかる改修をおこなったほどであり、これを記憶しているIBMの古参社員は「身の縮む思い」をおぼえているという[1]

また、計算対象の数値がベンフォードの法則に従って分布していた場合、計算対象として精度の低い数(仮数部の最上位4ビットが0b0001)の現れる確率は1/15にはならず、もっと高い[2]

エクセス64の単精度浮動小数点数では、符号部1ビット、指数部7ビット、仮数部24ビットで表現されている。各部は次のように定義されている。

  • 符号部は、0を正、1を負とする
  • 仮数部は、1未満の16進小数とする
  • 指数部は、16を基数とした指数に64をバイアスした値で表す

符号部は仮数の符号を表す。 指数部は-1663~-16-64と16-64~1663の範囲が表現できる。これを下回れば算術アンダーフロー、上回れば算術オーバーフローとなる。

エクセス64で表現するまでの過程

1.5を単精度のエクセス64で表現するには、次のようになる。

(-1)0×1.5×160

仮数部は1未満でなければならないため、値を(この例では右へ)シフトする。ただし、基数が16で、コンピュータの内部表現は2進数であるため、シフト量は4ビットである(24 = 16)。加えて正規化し、その結果は次の通り。

(-1)0×0.09375×161

次に指数部をエクセス64で表現する。ただし、負の指数を表すために64をバイアスしなければならない。バイアスすると、0~127を表現できる指数が、-64~+63を表現できる指数になる(-64 + 64 = 0、63 + 64 = 127)。 よって、今回の例では以下のようになる。

(-1)0×0.09375×16(65 - 64)

実際には2進数で表現されているので、2進数に直す。

  • 符号部(1ビット):+→0
  • 仮数部(24ビット):0.09375→.000110000000000000000000
  • 指数部(7ビット):65→1000001

浮動小数点は、最上位ビットから符号部、指数部、仮数部の順に符号化するため

2進値:0 1000001 000110000000000000000000、16進値:41180000

エラー(誤差)

オーバーフロー/アンダーフロー
演算結果が指数部で表現できる範囲を超える場合があるが、最大値を超えた場合はオーバーフロー、絶対値の最小より小さい場合はアンダーフローという。IEEE 754の場合、アンダーフローは、まず結果が非正規化数となり精度が低下し、さらに進むと結果が0になる。
桁落ち
絶対値がほぼ等しい異符号の数値同士の加算後や、同符号でほぼ等しい数値同士の減算の後、正規化有効数字が減少すること。詳細は桁落ちを参照。
情報落ち
浮動小数点数値を加減算するとき、指数を揃えなければならない。指数は絶対値の大きい方に揃えるが、このときに絶対値の非常に小さな値と絶対値の非常に大きな値との加減算を行うと、絶対値の大きな値の指数に揃えなければならないため、絶対値の小さな値は仮数部が大きく右シフトされ、仮数部の表現範囲からあふれて情報が欠落してしまう。情報欠落ともいう。詳細は情報落ちを参照。
積み残し
情報落ちが繰り返し起こる場合を言う。たとえば を n=0 の初項から計算しようとすると、ある項から情報落ちが起こり、それ以降の項が無視されてしまうことになる。これを積み残しと呼び、値の小さな項から加算をすることで対処する。
丸め誤差
仮数部の桁数が有限であるため、収まらない部分の最上位桁で四捨五入(2進法では0捨1入)して仮数部の桁数に丸めることによる誤差。

関連項目

参考文献

  1. ^ パターソン&ヘネシー『コンピュータの構成と設計 第3版 別冊 歴史展望』第3章 pp. 53-55
  2. ^ 『ハッカーのたのしみ』15章3節(pp. 283-285)

外部リンク

  • 浮動小数点演算について (1991 年 3 月発行の "Computing Surveys" に掲載された "Every Computer Scientist Should Know About Floating-Point Arithmetic" 稿 (David Goldberg著) を再編集したもの)