規格 - 浮動小数点数

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

浮動小数点数とは、実数の表現方法の1つであり、2進数の有限桁数で表された数値である。(対義語は、固定小数点数)
小数点の位置を変えて表現するため、浮動(動く)の小数点と呼ばれる。

固定小数点数は、小数点の位置を固定して表現される。

以下に、浮動小数点数の例を示す。

1.5(10) = 1.1(2)
3.25(10) = 11.01(2)


> 理論的には小数が無限に続く値でも、その内の有限個の桁数でその値を表す。
例えば、0.1を浮動小数点数で表すと、0.1(10) = 0.000110011001100110011...(2)と無限に続くが、コンピュータ内部では有限桁で丸められるため、
真値ではなく、近似値で表現することになる。


IEEE 754形式

例: IEEE754形式 (単精度浮動小数点数) への変換

IEEE 754 単精度浮動小数点数は、コンピュータで浮動小数点数を表現するための標準規格である。
これにより、異なるコンピュータやプログラム間で一貫した数値演算が可能になる。

単精度浮動小数点数は、32ビット (4バイト) で表現される。
その内訳を以下に示す。

  • 符号部 : 1ビット
    符号部は、数値の正負を表す。
    0 = 正の数
    1 = 負の数
  • 指数部 : 8ビット
    指数部は、数値を2の何乗するかを示す。
    指数部はバイアス (基準となる値) として127を用いたバイアス形式で表現される。
    実際の指数Eは、ストアされる指数値eからバイアスを減算することにより求められる。

    最小の正規化指数:
    最大の正規化指数:
  • 仮数部 : 23ビット
    仮数部は、数値の有効桁 (精度) を表す。
    仮数部は、通常、1.XXXX...の形で表現され、仮数部にはこの小数部分が格納される。 (先頭の1は省略される)


例: 9.875(10)

以下の例では、 をIEEE754形式の浮動小数点に変換している。

  1. 10進数を2進数に基数変換する
    まず、 を2進数に基数変換する。
    整数部分の は、2進数で 、小数部分の は2進数で となる。
    この2つ合わせると、 となる。

  2. 2進数を指数表記にする。(正規化)
    を指数表記にする。
    指数表記では、仮数が10未満の小数を含む数にする。
    つまり、 という形に正規化する。
    これを、ケチ表現と呼ぶ。

    したがって、仮数を した という形になる。

  3. 浮動小数点数のビットに格納する
    指数表記から浮動小数点数に格納する数に変換する。

    • 符号部
      は正であるため、IEEE754形式の仮数部は となる。
    • 指数部
      の指数は であるため、(8ビットの)2進数にすると となる。
      この を加算すると、 となる。
    • 仮数部
      上記で求めた仮数 の小数点以下の数 を仮数部の先頭から格納する。
      以降の数は でパディングする。

  4. 変換完了
    これにより、 をIEEE754形式の32ビットの浮動小数点数にした値は となる。


例: 0.3125(10)

以下の例では、 をIEEE754形式の浮動小数点に変換している。

  1. 10進数を2進数に基数変換する
    まず、 を2進数に基数変換する。
    整数部分は 、小数部分の は2進数で となる。
    この2つ合わせると、 となる。

  2. 2進数を指数表記にする。(正規化)
    を指数表記にする。
    指数表記では、仮数が10未満の小数を含む数にする。
    つまり、 という形に正規化する。 (ケチ表現)

    したがって、仮数を した という形になる。

  3. 浮動小数点数のビットに格納する
    指数表記から浮動小数点数に格納する数に変換する。

    • 符号部
      は正であるため、IEEE754形式の仮数部は となる。
    • 指数部
      の指数は であるため、(8ビットの)2進数にすると となる。
      この を加算すると、 となる。
    • 仮数部
      上記で求めた仮数 の小数点以下の数 を仮数部の先頭から格納する。
      以降の数は でパディングする。

  4. 変換完了
    これにより、 をIEEE754形式の32ビットの浮動小数点数にした値は となる。


例: 01000000101000000000000000000000(2)

例えば、以下に示すような単精度浮動小数点数があるとする。

01000000101000000000000000000000


この単精度浮動小数点数を、符号部、指数部、仮数部に分解する。

  • 符号部
    0 (正の数)
  • 指数部
    10000001(2) = 129(10)
    実際の指数
  • 仮数部
    01000000000000000000000(2)は、10進数で1.25(10)


したがって、この数値は以下に示すように解釈される。


例: IEEE754形式 (倍精度浮動小数点数) への変換

IEEE 754 倍精度浮動小数点数 (double-precision floating-point number) は、コンピュータで浮動小数点数を表現するための標準規格である。
これにより、異なるコンピュータやプログラム間で一貫した数値演算が可能になる。

倍精度浮動小数点数は、64ビット (8バイト) で表現される。
その内訳を以下に示す。

  • 符号部 (Sign bit) : 1ビット
    符号部は、数値の正負を表す。
    0 = 正の数
    1 = 負の数
  • 指数部 (Exponent) : 11ビット
    指数部は、数値を2の何乗するかを示す。
    指数部はバイアス (基準となる値) として1023を用いたバイアス形式で表現される。
    実際の指数Eは、ストアされる指数値eからバイアスを減算することにより求められる。

    最小の正規化指数:
    最大の正規化指数:
  • 仮数部 (Mantissa or Significand) : 52ビット
    仮数部は、数値の有効桁 (精度) を表す。
    仮数部は、通常、1.XXXX...の形で表現され、仮数部にはこの小数部分が格納される。 (先頭の1は省略される)


IEEE 754 倍精度浮動小数点数は以下の形式で表される。

  • S : 符号部
  • M : 仮数部
  • E : 指数部


例 : 倍精度浮動小数点数

例えば、以下に示すような倍精度浮動小数点数があるとする。

0100000000110100000000000000000000000000000000000000000000000000


この倍精度浮動小数点数を、符号部、指数部、仮数部に分解する。

  • 符号部
    0 (正の数)
  • 指数部
    10000000011(2) = 1027(10)
    実際の指数
  • 仮数部
    0100000000000000000000000000000000000000000000000000(2)は、10進数で1.25(10)


したがって、この数値は以下に示すように解釈される。


特殊な値

  • ゼロ
    符号部が0または1で、指数部と仮数部が全て0の場合
  • 無限大
    符号部が0または1で、指数部が全て1、仮数部が全て0の場合
  • NaN (Not a Number)
    指数部が全て1で、仮数部が0以外の場合



浮動小数点数の構造

ケチ表現 (正規化数) について

仮数部は、2進数で1.xxxxx...という形式で表現される。
小数点の前の1は暗黙的に存在する (ケチ表現) とみなされる。

そのため、例えば、仮数部が23ビットの場合は実質24ビット分の精度を得ることができる。

単精度浮動小数点数(float型)

単精度浮動小数点数(float型)は、4バイトのサイズを持ち、符号部(1bit)、指数部(8bit)、仮数部(23bit)で表す。

指数部は、-127のバイアスが掛かる。
仮数部は、仮数の小数点以下を表す。すなわち、仮数は仮数部の先頭に1(ケチ表現)を付加したものとなる。

単精度浮動小数点数(float型)の表す値 = (-1)符号部 × 2(指数部 - 127) × 1.仮数部


  • 仮数部 : 2進数から10進数への変換
    2進数24桁は、


したがって、単精度浮動小数点数(float型)の精度(有効桁数)は、2進数では24 (= 23 + 1) 桁、10進数では約7桁となる。

指数部も有限であるため、単精度浮動小数点数(float型)で表すことのできる実数の絶対値は、以下の範囲に限られる。


C言語において、単精度浮動小数点数の下限値および上限値は、float.hファイルのFLT_MINおよびFLT_MAXというマクロで定義されている。

 #include <stdio.h>
 #include <float.h>
 
 int main()
 {
    printf("FLT_MIN = %e,  FLT_MAX =%e\n", FLT_MIN, FLT_MAX);
 
    return 0;
 }


倍精度浮動小数点数(double型)

倍精度浮動小数点数(double型)は、単精度浮動小数点数(float型)に比べて、倍の精度(8byte)を持ち、符号部(1bit)、指数部(11bit)、仮数部(52bit)で表す。

指数部は、-1023のバイアスが掛かる。
仮数部は、仮数の小数点以下を表す。
すなわち、仮数は仮数部の先頭に1 (ケチ表現) を付加したものとなる。

倍精度浮動小数点数(double型)の表す値 = (-1)符号部 × 2(指数部 - 1023) × 1.仮数部


  • 仮数部 : 2進数から10進数への変換
    2進数24桁は、


したがって、倍精度浮動小数点数(double型)の精度(有効桁数)は、2進数では53 (= 52 + 1) 桁、10進数では約15桁 (16桁弱) となる。

指数部も有限であるため、倍精度浮動小数点数(double型)で表すことができる実数の絶対値は、以下の範囲に限られる。


C言語において、単精度浮動小数点数の下限値および上限値は、float.hファイルのDBL_MINおよびDBL_MAXというマクロで定義されている。

 #include <stdio.h>
 #include <float.h>
 
 int main()
 {
    printf("DBL_MIN = %e,  DBL_MAX =%e\n", DBL_MIN, DBL_MAX);
 
    return 0;
 }


現在のコンピュータでは、float型よりもdouble型を使用することが多い。
その理由として、以下が挙げられる。

  • 精度が良い。
  • 計算速度が速い。


計算速度が速い理由は、現在のコンピュータには、double型のデータを扱う専用回路が存在するからである。
float型の計算を行う場合、double型に変換した後、double型の専用回路で計算して、再度float型に変換するため、float型の方が計算時間が多く掛かる。


浮動小数点数の誤差

丸め誤差

仮数部が循環小数となる場合、仮数(の桁)が有限になるため、特定の桁数で四捨五入・切り捨て等を行うことにより発生する誤差である。
10進数を2進数に変換する時に、発生する誤差のことである。

桁落ち

桁数が決まっている浮動小数点数において、絶対値がほぼ等しい数値を減算した時に、実際の数値と比べて著しく桁数が減る誤差のことである。
(桁が落ちるのは、基本的に少数以下の部分である)

絶対値がほぼ等しい値同士を減算する場合、その差異は非常に小さな値となる。
浮動小数点数では桁数が決まっているため、非常に小さい値は切り捨てられる場合が多い。
この値を正規化する時、非常に小さい値は切り捨てられているため、0となり、実際の数値より小数点以下の桁数が大きく減ってしまう。

例.
以下のような絶対値のほぼ等しい値があるとする。
A = 1.1111111123334455667788
B = 1.111111111111111111111122

A - Bを行った後、正規化する。
1.2223344556666×10-7 (1)

上記を、有効桁数10桁の浮動小数点数で計算する。
a = 1.111111123
b = 1.111111111

a - bを行った後、正規化する。
1.200000000×10-7 (2)

上記の(1)を有効桁数10桁に変換する。
(2)は(1)と比べて桁数が減少して、ほぼ等しい値にも関わらず、大きな誤差が生じていることが分かる。
1.222334455×10-7 … (1)
1.200000000×10-7 … (2)

情報落ち

絶対値の差が非常に大きい2つの値の加減算を行う場合、小さい値が無視される誤差のことである。
桁数の決まっている浮動小数点数の計算において発生する誤差である。

浮動小数点数の加減算は、指数部を大きい方に揃えてから仮数部同士の計算をするため、値の差が大きいと小さい値は指数を大きくするために仮数部が0になるからである。

例 以下のような大きな値と小さい値があるとする。
A=1100000000000
B=0.11

両方の値を有効桁数10桁の浮動小数点数に変換する。
a = 1.100000000×1012
b = 1.100000000×10-1

この時、bの指数をaに合わせると仮数部が0となり情報が落ちる。
b = 0.000000000×1012

打ち切り誤差

無限小数等の値に対して、ある程度の時点で処理を打ち切ることで発生する誤差のことである。

丸め誤差との違いを以下に示す。

  • 丸め誤差
    10進数から2進数に変換する場合等に、特定の桁数で四捨五入や切り捨て等を行うことで生じる誤差。
  • 打ち切り誤差
    円周率等の無限小数が続く計算を途中で止めることで生じる誤差。