浮動小数点数

浮動小数点数は、実数をコンピュータで処理するために有限桁の小数で近似値として扱う方式であり、コンピュータの数値表現として広く用いられている。多くの場合、1ビットの符号部、固定長の指数部、固定長の仮数部、の3つの部分を組み合わせて、数値を表現する。

1. 概要
-----

この節はパターソンらの記述に基づく。

実数は0以上かつ1以下のような有限の範囲でも、無限個の値が存在するため、コンピュータでは妥当なビット数で有限個の値の近似値で扱う必要がある。

実数-1/3は無限小数となるが、有限桁の小数で近似値を表記できる。下の例では10進数での4桁としている。

-1/3 -1 x 0.33333333333333... -1 x 0.3333 x 100 -1 x 3.333 x 10-1下の2つの表記は科学記数法  とよばれ、小数点より左側の整数部分を1桁とする。 科学記数法のうち、左側の1桁を0以外にしたものを、正規化数  とよび、 一番下の表記が該当する。

実数-1/3はまた、有限桁2進数の小数でも、近似値で表記できる。下の例では2進数17桁としている。

-1/3 -1 x 0.01010101010101010101010101010101... -1 x 0.0101010101010101 -1 x  -1 x  -0.3333282472進数の小数も科学記数法で表記できる。

-1 x 0.0101010101010101 x 20 -1 x 0.101010101010101 x 2-1 -1 x 1.01010101010101 x 2-2上記は同じ値を、小数点位置を移動し異なる表記にしているため、浮動小数点と呼ばれる。一番下の表記は、正規化数である。

コンピュータ処理に適した暗黙の基数2について、符号  S、仮数  F、指数  Eにより、 浮動小数点数は下記の式で表記できる。

S x F x 2E

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

浮動小数点数のフォーマットには、以下で説明するものの他、以前は多数あった。

IEEE方式
IBM方式
指数部と仮数部を可変とする方式

2.1. IEEE方式
-----------

IEEE 754 形式の

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

符号部は、 0 を正、1 を負とする
仮数部は、整数部分が 1 であるような2進小数の小数部分を表す
指数部は、符号なし2進整数とし、半精度では 15、単精度では 127、倍精度では 1023、四倍精度では 16383 のゲタを履かせたゲタ履き表現で表すつまり、IEEE 754 形式で表現する値は

半精度の場合： 符号部 × 2指数部 − 15 × 単精度の場合： 符号部 × 2指数部 − 127 × 倍精度の場合： 符号部 × 2指数部 − 1023 × 四倍精度の場合： 符号部 × 2指数部 − 16383 ×である。

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

通常の浮動小数点数を表現するのは、指数部が単精度で 254 ～ 1、倍精度で 2046 ～ 1の範囲のときである
指数部が、単精度の場合 255、倍精度の場合 2047のとき： 仮数部が 0 以外の場合は、非数を表す 仮数部が 0 の場合は、符号部が 0 のときは正の無限大、符号部が 1 のときは負の無限大を表す
指数部が 0のとき： 非正規化数
指数部、仮数部ともに 0 のときは ±0 を表す0 を 0 で割ろうとすると NaN になる。また、 も、求めるとNaNになる。

2.1.1. IEEE 754 で表現するまでの過程
--------------------------

2.5を例にとると、

仮数の符号は、+
仮数の絶対値は、2.5
IEEE 754の基数は、2で固定
指数は、0であることから、まず次のように考える。

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

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

0 ×  × 21
符号部は、0
仮数部は、0.25
指数は、1指数部は、指数に127をバイアスすることが決まっているため

0 ×  × 2
符号部は、0
仮数部は、0.25
指数部は、1282進法では、

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

2進値：0100、16進値：

2.1.2. bfloat16
---------------

IEEE 754 形式から派生した浮動小数点数の形式。符号部 1 ビット ・ 指数部 8 ビット ・ 仮数部 7 ビットである。

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

符号部 × 2指数部 − 127 ×である。

採用事例

インテル - Intel Xeon Cooper Lake マイクロアーキテクチャ以降、Nervana NNP-L1000 など
ARMアーキテクチャ - Armv8.6-A
Google - Tensor Processing Unit 2.0 以降
NVIDIA - Ampere マイクロアーキテクチャ以降
Amazon.com - AWS Inferentia、Amazon Elastic Inference など

2.1.3. FP8
----------

IEEE 754 形式から派生した浮動小数点数の形式。以下の2種類がある。

E4M3 - 符号部 1 ビット ・ 指数部 4 ビット ・ 仮数部 3 ビット
E5M2 - 符号部 1 ビット ・ 指数部 5 ビット ・ 仮数部 2 ビット採用事例

NVIDIA - Hooper マイクロアーキテクチャ以降

2.2. IBM方式
----------

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

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

また、計算対象の数値がベンフォードの法則に従って分布していた場合、計算対象として精度の低い数の現れる確率は1/15にはならず、もっと高い。

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

符号部は、0を正、1を負とする
仮数部は、1未満の16進小数とする
指数部は、16を基数とした指数に64をバイアスした値で表す符号部は仮数の符号を表す。 指数部は−1663～−16−64と16−64～1663の範囲が表現できる。

2.2.1. IBM方式で表現するまでの過程
----------------------

1.5を単精度のIBM方式で表現するには、次のようになる。

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

0 × 0.09375 × 161次に指数部を、64をバイアスしたゲタ履き表現で表現する。バイアスにより、0～127のビットパターンで、整数値−64～+63を表現するということになる。 よって、今回の例では以下のようになる。

0 × 0.09375 × 162進法では、

符号部：+ → 0
仮数部：0.09375 → 000110000000000000000000
指数部：65 → 1000001浮動小数点は、最上位ビットから符号部、指数部、仮数部の順に符号化するため

2進値：0 1000001 000110000000000000000000、16進値：

2.3. 指数部と仮数部を可変とする方式
--------------------

任意精度演算と、従来の指数部と仮数部を共に固定長とする形式の中庸と言えるような方式が、いくつか提案されている。絶対値が1に近い値では指数部の桁数を短くし、仮数部の桁数を多くとって、よく使われる値を精度よく表現する。絶対値が極端に大きい値や小さい値には、精度とひきかえに指数部の桁数を増やすことで対応する。以下で述べる方式を提案している文献では、アプリケーションとして、通常の浮動小数点計算には、指数が大きくなり過ぎることがあって向かないとされている:en:Graeffe's methodをうまく扱えたという例が示されている。

2.3.1. 松井・伊理の表現法
----------------

松井正一と伊理正夫が提案した方式で、符号と絶対値による表現法である。論文中に示された例では、64ビットの倍精度浮動小数点数として、仮数部の長さnを示す情報6ビットと、mビットの指数部とnビットの仮数部からなる。彼らは、オーバーフローを起こさせないための、より大きい数やより小さい数の表現や、無限大などの例外的な値を含めた算術も提案している。

2.3.2. 浜田のURR
-------------

浜田穂積が提案した方式で、Universal Representation of Real numbersの意でURRと名付けられている。−∞ ～ 0 ～ ∞ の区間を、次のように分割しながら、二進法による表現に対応付ける、というのが基本的な考え方で、「符号と絶対値」形ではなく、浮動小数点の表現としては比較的珍しい2の補数の形をしている。

100 = −∞
101 = −2
110 = −1
111 = −0.5
000 = 0
001 = 0.5
010 = 1
011 = 2 ～ ∞ここで±1の前後は、区間の両端の比が2なので、指数部の表現は終わったとみなすことができ、残りの桁は仮数部のように扱う。次のように分割を続ける。

1000 = −∞
1001 = −4
1010 = −2
1011 = −1.5
1100 = −1
1101 = −0.75
1110 = −0.5
1111 = −0.25
0000 = 0
0001 = 0.25
0010 = 0.5
0011 = 0.75
0100 = 1
0101 = 1.5
0110 = 2
0111 = 4 ～ ∞以降は、符号ビットが0である0 ～ 0.5 と 2 ～ ∞ の区間に絞って説明する。

0 00000 = 0
0 00001 = 0.00390625 
0 00010 = 0.0625 
0 00100 = 0.25 
0 01000 = 0.5 
0 11000 = 2
0 11100 = 4
0 11110 = 16
0 11111 = 256 ～ ∞ここで、2 = 220、4 = 221、16 = 222、256 = 223 である。このように 0 や ±∞ を含む区間は「二重指数分割」する。

0 000000 = 0
0 000001 = 0.0000152587890625 
0 000010 = 0.00390625 
0 000011 = 0.015625 
0 000100 = 0.0625 
0 000110 = 0.125 
0 001000 = 0.25 
0 111000 = 4 
0 111010 = 8 /2)
0 111100 = 16 
0 111101 = 64 /2)
0 111110 = 256 
0 111111 = 65536 ～ ∞このように、区間の両端の比が2より大きい場合は、「等比分割」する。

以上のような操作の結果として、指数部が0以上の場合は

"0 10" = 0
"0 110" = 1Bn 指数部が0未満の場合は

"0 01" = 上述の"0 10"の符号ビット以外をビット反転させたもの = 2進数"0"をビット反転させたもの = −1
"0 001" = 上述の"0 110"の符号ビット以外をビット反転させたもの = 2進数"1Bn"をビット反転させたもの = −−1ビット反転して0以上にした後に上述の方法を適用した指数部を、再びビット反転したものとなる。 こうして、負数に拡張されたガンマ符号によって自分の長さを含む指数部と、残りの仮数部から成る、と見ることができるような表現が得られる。

利点として、ビット表現を固定小数点数と解釈しても値・絶対値の大小関係が一致しているため、

単精度と倍精度、さらには4倍精度や、一部ビットをデータ型判別などの別用途に転用している処理系で用いられる7bitや30bitなど、任意のビット長表現との相互変換・丸め操作が、この方式では単に最下位ビットを追加したり切り捨てるだけで良い
大小関係の比較演算や符号反転に必要なハードウェア・計算量が、整数でのそれと同一という点が挙げられる。また、1の近くでは桁数のほとんどが仮数部となるので精度が高い。

欠点としては、精度が変化するため従来の精度一定を前提としたノウハウに修正が必要かもしれない、−∞を除くワードのあらゆるビット表現に浮動小数点数としての意味が与えられるため、例外的な値を表現する方法を別に考えなければいけない、などといった点がある。浜田は1000...を符号なしの∞とし、表現可能な最大と最小の絶対値を持つ値を、具体的にその値を表すのではなく±∞と±0を表現するものとする、という方法を提案している。

この表現法の初出は1981年だが、1983年に改良版が提案されているのでそちらをまずは参照すべきである。

いくつかの実装の報告や改良の提案などがある。

2.3.3. GustafsonのPosit
----------------------

この方法は浜田方式のリバイバルのようなものである。

[1]
[2]

3. エラー
------

オーバーフロー／アンダーフロー 演算結果が指数部で表現できる範囲を超える場合があるが、最大値を超えた場合はオーバーフロー、絶対値の最小より小さい場合はアンダーフローという。IEEE 754の場合、アンダーフローは、まず結果が非正規化数となり精度が低下し、さらに進むと結果が0になる。 桁落ち 絶対値がほぼ等しい異符号の数値同士の加算後や、同符号でほぼ等しい数値同士の減算の後、正規化で有効数字が減少すること。詳細は桁落ちを参照。 情報落ち 浮動小数点数値を加減算するときはまず指数を揃えなければならない。絶対値の非常に小さな値と絶対値の非常に大きな値との浮動小数点数の加減算を行うときは、まず指数を絶対値の大きい方に揃える桁合わせを行ない、それから加減算を行なう。そのため絶対値の小さな値は仮数部が右側に多くシフトされて下位の桁の部分が反映されずに結果の値が丸められて情報が欠落する。情報欠落ともいう。詳細は情報落ちを参照。 積み残し 情報落ちが繰り返し起こる場合を言う。たとえば を n=0 の初項からn=100に向かって順番に加えて計算しようとすると、ある項から先で情報落ちが起こり、それ以降の項は無視されてしまうことになる。これを積み残しと呼ぶ。値の小さい項から大きい項に向かって加算をすることで対処できる場合もある。対処としては、有理数演算などによって無誤差の計算を行うか、カハンのsummationアルゴリズムなどいくつかの効率的な手法が提案されている。 丸め誤差 仮数部の桁数が有限であるため、収まらない部分の最上位桁で四捨五入して仮数部の桁数に丸めることによる誤差。

4. 脚注
-----

4.1. 注釈
-------

4.2. 出典
-------

5. 参考文献
-------

IEEE 754 http://grouper.ieee.org/groups/754/
"IEEE Standard for Binary Floating-Point Arithmetic", IEEE, ISBN 978-9996639524, .
Peter J. L. Wallis : "Improving Floating-Point Programming", Wiley, ISBN 978-0471924371,.
Michael L. Overton:"Numerical Computing With IEEE Floating Point Arithmetic", SIAM, ISBN 978-0898714821, .
Jean-Michel Muller:"Elementary Functions: Algorithms and Implementation", 2nd ed., Birkhaeuser, ISBN 978-0817643720, .
Jean-Michel Muller:"Handbook of Floating-Point Arithmetic", Birkhaeuser, ISBN 978-0817647049, .
Peter Kornerup, David W. Matula: "Finite Precision Number Systems and Arithmetic", Cambridge University Press, ISBN 978-0521761352, .

6. 関連項目
-------

コンピュータの数値表現
固定小数点数
単精度浮動小数点数
誤差、端数処理
エクセス3
二進化十進表現
精度保証付き数値計算

7. 外部リンク
--------

[3]