Hayami Kaito Web
← Apps

浮動小数点数(IEEE 754)

10 進の数が、符号・指数部・仮数部のビット列にどう丸められて保存されるかを見せます。半精度・単精度・倍精度などの形式と丸めの向きを変えて、0.1 + 0.2 の誤差や桁落ち、非正規化数・∞・NaN を確かめられます。

binary32。C の float、GPU のシェーダー、JavaScript の Math.fround・Float32Array など。10 進でおよそ 7 桁の精度です。(符号 1・指数 8・仮数 23 ビット)

丸めの向き

一番近い値に丸め、ちょうど中間なら仮数の最後のビットが 0(偶数)のほうを選びます。ふつうの計算はすべてこれです。

10 進では短い 0.1 も、2 進では 0.0001100110011… と無限に続くので、途中で丸めた近い値が保存されます。

ビット列

ビットを押すと 0 と 1 が入れ替わります。左が最上位ビットです。

符号(1 ビット)

指数部(8 ビット)

仮数部(23 ビット)

ビット列の読み方

符号
0 → 正(+)
指数部
01111011(2 進) → 123 − バイアス 127 = -4
仮数部
1.10011001100110011001101(2 進) = 1.600000023841858

(−1)0 × 1.600000023841858 × 2-4 = 0.1

保存される値

種類
正規化数
正確な値
0.100000001490116119384765625
最短の表記
0.1(読み直すと同じビット列に戻る一番短い 10 進)
ULP(隣との間隔)
7.451e-9
入力とのずれ
1.490e-9相対 1.490e-80.2 ULP

周りの浮動小数点数

縦線が表せる値です。そのあいだの数は表せないので、入力した値は近くの線(丸めの向きに合う線)に丸められます。

0.099999990.0999999940.10.100000010.10000002入力した値

四則演算

浮動小数点数の計算は「保存されている 2 つの値で正確に計算し、結果を 1 回だけ丸める」と決められています。入力した数のまま計算した数学の答えと比べます。

ビット列最短の表記正確な値
左の数 0.13DCCCCCD0.10.100000001490116119384765625
右の数 0.23E4CCCCD0.20.20000000298023223876953125
保存した値で正確に計算——0.300000004470348358154296875
結果 0.1 + 0.23E99999A0.30.300000011920928955078125
数学の答えを丸めた値3E99999A0.30.300000011920928955078125

結果は数学の答え(3/10(≈ 0.3))を丸めた値と同じで、これ以上近い値はありません。

形式の比較

入力した値(0.1)を各形式で保存したときの値と、入力からのずれも並べます。

形式指数 / 仮数バイアス最大の値最小の正規化数最小の非正規化数イプシロン10 進の桁保存される値相対誤差
8 ビット4 / 372400.015630.0019530.1251.20.10.01563
半精度(16)5 / 1015655046.104e-55.960e-80.00097663.30.10.0002441
bfloat168 / 71273.390e381.175e-389.184e-410.0078132.40.10.0009766
単精度(32)8 / 231273.403e381.175e-381.401e-451.192e-77.20.11.490e-8
倍精度(64)11 / 5210231.798e3082.225e-3084.941e-3242.220e-1616.00.15.551e-17

表せる数の並び(8 ビット)

8 ビットの形式で表せる 0 以上の有限の値(120 個)を数直線に並べます。指数が 1 増えるごとに間隔が 2 倍に広がるので、0 に近いほど詰まっています。短い線は非正規化数で、0 の近くを等しい間隔で埋めています。

0481216

0〜16 にある値: 89 個(0〜1 に 57 個、1 より大きい値は 63 個)

使い方

  • 形式(8 ビット・半精度・bfloat16・単精度・倍精度)と、丸めの向きを選びます。
  • 10 進の数(1.5・-2.5e-3)や分数(1/3)を入力すると、その形式で保存されるビット列と、丸めた正確な値・入力とのずれを表示します。16 進のビット列を直接入力することもできます。
  • ビットを押すと 0 と 1 が入れ替わり、値がどう変わるかを確かめられます。「1 つ小さい値」「1 つ大きい値」で、隣の浮動小数点数に移れます。
  • 「四則演算」では、2 つの数の計算結果と、数学の答えを丸めた値を比べます。例のボタンで 0.1 + 0.2 や桁落ちの例を呼び出せます。

浮動小数点数のしくみ

IEEE 754 の浮動小数点数は、数を「符号 × 1.xxx(2 進)× 2 の指数乗」の形で表し、符号・指数部・仮数部の 3 つのビットの並びに詰めます。正規化数では仮数の先頭は必ず 1 なので、そのビットは保存しません(けち表現)。指数部には、実際の指数にバイアス(単精度なら 127)を足した値を入れ、負の指数も 0 以上の整数で表します。

指数部がすべて 0 の値は非正規化数で、先頭の 1 を省かずに最小の指数のまま仮数を小さくしていき、0 との間をなめらかにつなぎます。指数部がすべて 1 の値は特別な値で、仮数部が 0 なら ∞、それ以外なら NaN(非数)です。0 にも符号があり、+0 と -0 は等しいとみなされますが、1 を割ると ±∞ に分かれます。

丸めと誤差

仮数のビット数には限りがあるので、表せる数は飛び飛びです。隣どうしの間隔を ULP(unit in the last place)と呼び、指数が 1 増えるごとに 2 倍に広がります。入力した数は表せる数のどれかに丸められ、最近接の丸めならずれは 0.5 ULP 以下です。10 進では短い 0.1 も 2 進では無限に続くため、正確には保存できません。

計算は、保存されている 2 つの値で正確に計算した結果を 1 回だけ丸めます。それでも 0.1 + 0.2 が 0.3 にならないのは、0.1 と 0.2 を保存したときの誤差が足し合わされるためです。大きさの違う数を足すと小さいほうが消える「情報落ち」や、近い数どうしを引くと誤差の割合が大きくなる「桁落ち」も、この丸めから起こります。

このアプリは BigInt を使った分数で正確な値を計算し、自前で丸めています。単精度と倍精度の結果は、ブラウザの Float32Array・number と同じビット列になります。