オーバーフローとアンダーフロー
この章の目標
オーバーフローとアンダーフローの定義を理解し、IEEE 754 での扱いと非正規化数の役割を学び、典型的な発生場面と回避技法を身につける。
前提知識
IEEE 754 浮動小数点数の基本構造
1. オーバーフロー
オーバーフロー(Overflow)とは、演算結果の絶対値が浮動小数点数で表現可能な最大値を超える現象である。
| 精度 | 最大値 $x_{\max}$ | 最大指数 |
|---|---|---|
| 単精度(float32) | $\approx 3.4 \times 10^{38}$ | $2^{127}$ |
| 倍精度(float64) | $\approx 1.8 \times 10^{308}$ | $2^{1023}$ |
IEEE 754 ではオーバーフロー時に結果は $\pm\infty$(無限大)にセットされる。$\infty$ に対する演算は $\infty + 1 = \infty$, $\infty \times 2 = \infty$, $\infty - \infty = \text{NaN}$ などの規則に従う。
2. アンダーフロー
アンダーフロー(Underflow)とは、演算結果の絶対値がゼロでないにもかかわらず、表現可能な最小正規化数より小さくなる現象である。
| 精度 | 最小正規化数 $x_{\min}$ | 最小非正規化数 |
|---|---|---|
| 単精度(float32) | $\approx 1.2 \times 10^{-38}$ | $\approx 1.4 \times 10^{-45}$ |
| 倍精度(float64) | $\approx 2.2 \times 10^{-308}$ | $\approx 5.0 \times 10^{-324}$ |
アンダーフローはオーバーフローに比べて致命的ではないことが多い。IEEE 754 の段階的アンダーフローにより、結果はゼロに「突然フラッシュ」されるのではなく、精度を徐々に失いながらゼロに近づく。
3. IEEE 754 における扱い
IEEE 754 の特殊値:
- $\pm\infty$: オーバーフローの結果。$1/0 = +\infty$, $-1/0 = -\infty$ なども含む。
- NaN(Not a Number): $0/0$, $\infty - \infty$, $\sqrt{-1}$ など、定義されない演算の結果。
- $\pm 0$: 正のゼロと負のゼロが区別される。$1/(+0) = +\infty$, $1/(-0) = -\infty$ となる。
4. 非正規化数(デノーマル数)
非正規化数(denormalized number / subnormal number)は、指数部が最小値のときに仮数部の暗黙の先頭ビット1を0とすることで、$x_{\min}$ より小さい数を表現する仕組みである。
非正規化数により、$x - y = 0 \Leftrightarrow x = y$ という重要な性質が保証される(アンダーフローのフラッシュ・トゥ・ゼロ方式ではこの性質が壊れる)。
ただし、非正規化数の有効桁数は正規化数より少なく、一部のプロセッサでは非正規化数の演算が著しく遅い(100倍以上)という性能上の問題がある。
5. 典型的な発生場面
オーバーフロー
- 階乗: $170! \approx 7.26 \times 10^{306}$ は倍精度の範囲内であるが、$171! \approx 1.24 \times 10^{309}$ でオーバーフローする。
- 指数関数: $e^{709} \approx 8.2 \times 10^{307}$ は倍精度の範囲内であるが、$e^{710}$ でオーバーフローする。
- ベクトルのノルム: $\|x\|_2 = \sqrt{\sum x_i^2}$ で $x_i$ が大きいと $x_i^2$ でオーバーフローする。
アンダーフロー
- 確率の積: 多数の小さい確率の積はアンダーフローしやすい。対数空間で計算する(対数確率)。
- 指数関数の減衰: $e^{-x}$ で $x > 745$ (倍精度)ではアンダーフローしてゼロになる。
- ガウス分布の密度関数: 遠い点での $e^{-x^2/2}$ は非常に小さい。
6. 回避技法
対数スケールでの計算
積を和に変換する。$\prod p_i$ の代わりに $\sum \log p_i$ を計算する。最終結果が必要なときだけ $\exp$ を適用する。
Log-Sum-Exp トリック
$\log\left(\sum_i e^{x_i}\right)$ を安定に計算するために、$M = \max_i x_i$ として
$$\log\left(\sum_i e^{x_i}\right) = M + \log\left(\sum_i e^{x_i - M}\right)$$と変形する。$x_i - M \le 0$ であるから $e^{x_i-M} \le 1$ となりオーバーフローしない。
スケーリング(正規化)
ベクトルのノルム $\|x\|_2$ を計算する際、$m = \max_i |x_i|$ で割ってから計算する。
$$\|x\|_2 = m \sqrt{\sum_i (x_i / m)^2}$$$(x_i/m)^2 \le 1$ であるからオーバーフローしない。LAPACK の dnrm2 はこの手法を用いている。
式の変形
$e^a / e^b$ は $e^{a-b}$ に、$\sqrt{a} \cdot \sqrt{b}$ は $\sqrt{ab}$ に変形すると中間値のオーバーフロー・アンダーフローを回避できることがある。
7. よくある質問
Q1. オーバーフローとは何ですか?
演算結果の絶対値が浮動小数点数で表現可能な最大値を超える現象である。IEEE 754 では結果は $\pm\infty$ となる。倍精度の最大値は約 $1.8 \times 10^{308}$ である。
Q2. アンダーフローとは何ですか?
演算結果の絶対値がゼロでないにもかかわらず、表現可能な最小正規化数より小さくなる現象である。IEEE 754 の段階的アンダーフロー(非正規化数)により、精度は低下するがゼロへの突然のフラッシュは避けられる。
Q3. オーバーフローやアンダーフローを回避する方法は何ですか?
対数スケールでの計算(log-sum-exp など)、式の変形による中間値の安定化、スケーリング、拡張精度演算の使用などがある。
8. 参考資料
- Wikipedia「算術オーバーフロー」(日本語版)
- Wikipedia「Arithmetic underflow」(英語版)
- Wikipedia「Denormal number」(英語版)
- D. Goldberg, "What Every Computer Scientist Should Know About Floating-Point Arithmetic," ACM Computing Surveys, vol. 23, no. 1, pp. 5--48, 1991.
- IEEE 754-2019, IEEE Standard for Floating-Point Arithmetic, IEEE, 2019.