TL

浮動小数点演算ユニットの内部 ─ 整列・正規化・丸めパイプライン

なぜ0.1+0.2が0.3にならないのか。FP加算の指数整列・正規化・最近接偶数丸めから、ガード/ラウンド/スティッキビット、FMAの単一丸めまでを原理で押さえ、数値誤差を制御できます。

応用浮動小数点FPUIEEE754丸めFMA最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.FP加算は指数整列→仮数加減算→正規化→丸めの4段で動き、整列で右シフトしたビットの欠落をガード/ラウンド/スティッキの3ビットで保持して正しく丸める。
  • 2.既定の丸めは最近接偶数(round half to even)で、ちょうど中間の値を最下位ビットが偶数になる側へ寄せ、統計的バイアスを打ち消す。
  • 3.FMA(融合積和)は積と和を中間丸めなしの1回の丸めで計算し、a*b+c の精度を改善する。非正規化数・NaN・Infは指数フィールドの特殊値として例外的に処理される。

浮動小数点数という土台

IEEE 754 の倍精度(binary64)は、64ビットを 符号1 / 指数11 / 仮数52 に分けます。実際の値は次のように再構成されます。正規化数では仮数の最上位に「1.」が暗黙に付く(ケチ表現、hidden bit)ため、有効ビットは実質53ビットです。

値 = (-1)^符号 × 1.仮数 × 2^(指数フィールド - 1023)
  仮数 = 暗黙の1 + 小数52ビット(= 53ビットの有効数字)
  1023 = 指数のバイアス(負の指数も符号なしで格納するため)

加算・乗算は整数演算のように「桁を揃えてそのまま足す」では済みません。指数が異なる2数を足すには小数点位置を合わせる必要があり、結果は再び正規形へ戻し、限られたビット幅へ丸める必要があります。FPU(浮動小数点演算ユニット)の内部パイプラインは、この一連を高速にこなす専用回路です。

FP加算の4段パイプライン

a + b を例に、FPUが踏む段階を追います。前提として指数の大きい側を a とします。

1. 指数整列(align)   : 指数差 d = exp(a) - exp(b) ぶん、bの仮数を右にdシフトして桁を合わせる
2. 仮数加減算(add)   : 整列後の仮数同士を加算(符号が異なれば減算)
3. 正規化(normalize): 結果の先頭1の位置に合わせ、左右シフトと指数の補正で「1.xxx」へ戻す
4. 丸め(round)       : 53ビットへ収め、はみ出した下位ビットを丸める。丸め桁上がりで再正規化が要ることもある

ここで本質的な難所が段1の右シフトです。指数差が大きいと、小さい側の仮数の有効ビットがレジスタ幅の外へ押し出されます。素朴に捨てると丸めが狂うため、追加の下位ビットを保持する仕組みが要ります。それがガード・ラウンド・スティッキの3ビットです。整数演算とは違い、シフトで失われる情報を「正しく丸めるぶんだけ」残すのがFPUの設計の核心です。

ガード・ラウンド・スティッキビット

仮数の最下位ビット(LSB)の右側に、丸め判定専用の3ビットを置きます。役割は次のとおりです。

ビット位置役割
ガード(G)LSBの1つ右丸め方向の判定に使う最初の桁
ラウンド(R)Gのさらに1つ右中間値(ちょうど0.5)かどうかの判定に使う
スティッキ(S)Rより下の全ビットそれより下に1が1つでもあれば1(論理和を畳んだ値)

スティッキビットがなぜ必要かが上級者の理解の分かれ目です。右シフトでこぼれ落ちたビットを1ビットも残さないと、「ちょうど中間(half)」なのか「中間より少し上」なのかを区別できません。スティッキは押し出された全下位ビットの論理和を1ビットに畳み込んだもので、「下にまだ端数が残っているか」を保持します。これにより、捨てた部分が正確に2分の1なのか、それを超えるのかを判定でき、最近接丸めが厳密に行えます。

仮数: ... b1 b0 | G R S
                  ↑ ここから下が丸め対象
G=0           → 切り捨て(下半分)
G=1, R=S=0    → ちょうど中間 → 最近接偶数規則を適用
G=1, (R or S) → 切り上げ(上半分)

最近接偶数丸め

IEEE 754 の既定モードは round half to even(最近接偶数、銀行家の丸め) です。最も近い表現可能値へ丸め、ちょうど中間のときだけ「結果のLSBが0(偶数)になる側」を選びます。

2.5 → 2(偶数側)   3.5 → 4(偶数側)   0.5 → 0
通常の「0.5切り上げ」だと中間値が常に上へ寄り、和に正のバイアスが蓄積する。
偶数丸めは中間値を上下へ半々に振り分け、誤差の期待値をゼロに近づける。

四捨五入(round half up)は中間値を常に切り上げるため、大量の加算で誤差が一方向に偏ります。偶数丸めはこの統計的バイアスを打ち消すのが狙いです。IEEE 754 はほかに、ゼロ方向・正の無限大方向・負の無限大方向への丸めも規定し、区間演算などで使い分けます。

正しい丸めと0.5 ulpの保証

IEEE 754 は四則演算と平方根について「無限精度で計算してから1回だけ丸めた結果」とビット単位で一致することを要求します。これを**正しい丸め(correctly rounded)**と呼び、誤差は最大でも0.5 ulp(unit in the last place、最下位ビット1個ぶん)に収まります。ガード/ラウンド/スティッキは、この0.5 ulp保証をハードウェアで成立させるための最小限の情報量だと理解すると腑に落ちます。

FMA ─ 単一丸めの精度向上

a*b + c は科学計算や行列積で頻出します。これを乗算命令と加算命令に分けると、丸めが2回入ります。積 a*b をいったん53ビットへ丸め、その丸め済みの値に c を足してまた丸める、という流れです。

FMA(Fused Multiply-Add、融合積和) は積と和を1命令で実行し、中間の丸めを省いて最後に1回だけ丸めます。積 a*b はフル幅(約106ビット)のまま保持され、c を加えてから53ビットへ丸めるため、中間丸めの誤差が消えます。

分離: round( round(a*b) + c )   ← 丸め2回。a*bの下位ビットが先に失われる
FMA : round( a*b + c )          ← 丸め1回。積を全幅で保持してから加算

FMAが効く典型が桁落ちを伴う計算です。たとえば a*a - b*b のように近い大きさの数を引く場面で、積を全幅で持てば下位の有効桁が保たれ、誤差が抑えられます。GPUの行列積やTensorコアの積和SIMDの内積が高速かつ高精度なのは、このFMA回路を多数並べているからです。

FMAの注意点

FMAは丸め回数が違うため、分離した乗算+加算とビット単位では一致しないことがあります。コンパイラが自動でFMAへ融合すると、最適化レベルやプラットフォームで結果が微妙に変わり、再現性が問題になる場合があります。逆に、わざとFMAを使って fma(a, b, -a*b) のように積の丸め誤差を取り出し、補正に使う(誤差フリー変換)テクニックもあります。

非正規化数・NaN・Infの例外処理

指数フィールドの**最小値(全0)と最大値(全1)**は通常の数には使わず、特殊な意味を割り当てます。FPUはこれらをパイプラインの外で例外的に処理します。

指数フィールド仮数意味
最小(全0)0符号付きゼロ(+0 と -0 が別表現)
最小(全0)0以外非正規化数(サブノーマル、暗黙の1を付けない)
最大(全1)0無限大(Inf、オーバーフローやx/0の結果)
最大(全1)0以外NaN(非数、0/0 や sqrt(-1) の結果)

非正規化数(サブノーマル) は、最小指数より小さい絶対値を段階的に表すための仕組みです。暗黙の先頭1を付けず、0.仮数 × 2^最小指数 として有効桁を削りながらゼロへ滑らかに近づけます(gradual underflow)。これによりゼロ近傍で a が b 未満 の差が突然ゼロに丸まる事故を防ぎますが、専用処理が要るためサブノーマルが絡む演算は極端に遅くなる実装が多く、性能上の落とし穴です。

NaN は伝播性を持ち、NaN を含む演算の結果はほぼ常に NaN になります。また NaN は自分自身とも等しくない(NaN == NaN は偽)という特異な性質があり、これを使って NaN を判定できます。Inf はオーバーフローやゼロ除算で生じ、符号を持ちます。

ゼロ除算と例外フラグ

浮動小数点のゼロ除算は整数のように即トラップせず、既定では Inf または NaN を返して計算を続行します。代わりにIEEE 754は無効演算・ゼロ除算・オーバーフロー・アンダーフロー・不正確の5つの例外フラグを立てます。これらは制御・ステータスレジスタ(x86のMXCSRなど)に蓄積され、後からまとめて確認できます。例外をトラップとして即座に捕まえるか、フラグとして溜めるかは設定で切り替えられます。

試験のポイント

「FP加算は指数整列→仮数加減算→正規化→丸めの順」「整列の右シフトで失う情報をガード/ラウンド/スティッキの3ビットで保持し、スティッキは下位の論理和」「既定の丸めは最近接偶数でバイアスを打ち消す」「FMAは中間丸めを省いた単一丸めで精度向上」「指数の全0/全1がサブノーマル・ゼロ・Inf・NaNの特殊値」の5点が頻出です。正しい丸めで誤差が0.5 ulp以内に収まる点も押さえましょう。

まとめ

  • IEEE 754 の浮動小数点加算は 指数整列・仮数加減算・正規化・丸め の4段で進み、整列の右シフトで桁を揃える。
  • 右シフトでこぼれるビットは ガード・ラウンド・スティッキ の3ビットに畳んで保持し、スティッキは押し出された全下位ビットの論理和で「端数の有無」を表す。
  • 既定の 最近接偶数丸め は中間値を偶数側へ寄せて統計的バイアスを打ち消し、正しい丸めにより誤差は0.5 ulp以内に収まる。
  • FMA は積を全幅で保持して最後に1回だけ丸め、a*b+c の精度と速度を両立する。
  • 指数フィールドの全0・全1は サブノーマル・ゼロ・Inf・NaN の特殊値で、パイプライン外の例外処理と例外フラグで扱う。

FPUの設計は、有限ビットの中で「失う情報を最小限だけ残し、偏りなく丸める」ための工学です。CPUパイプラインに組み込まれた多段FPUや、アウトオブオーダ実行による演算の重ね合わせを理解する土台として、整列・正規化・丸めの3要素は欠かせません。

CPU/メモリ/ディスク Article

浮動小数点演算ユニットの内部 ─ 整列・正規化・丸めパイプラインを実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

浮動小数点

比較で見る軸

難易度: advanced / カテゴリ: CPU/メモリ/ディスク / タグ数: 5

導入後に効く点

既定の丸めは最近接偶数(round half to even)で、ちょうど中間の値を最下位ビットが偶数になる側へ寄せ、統計的バイアスを打ち消す。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
CPU/メモリ/ディスク
タグ数
5

判断チェックリスト

  • 自社の用途が「浮動小数点 / FPU」に近いか確認する。
  • 強みである「FP加算は指数整列→仮数加減算→正規化→丸めの4段で動き、整列で右シフトしたビットの欠落をガード/ラウンド/スティッキの3ビットで保持して正しく丸める。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

浮動小数点FPUIEEE754丸めFMA浮動小数点FPUIEEE754
参考: 公式情報