浮動小数点のオーバーフローとアンダーフロー
浮動小数点計算が表現するには大きすぎる値(オーバーフロー)や小さすぎる値(アンダーフロー)を生成した場合に何が起こるか、IEEE 754がこれらのケースをどう処理するかを理解します。
Precision
Decimal Value
3.4028234663852886e+38
Float32 Hex
0x7F7FFFFF
Float64 Hex
0x47EFFFFFE0000000
詳細な説明
オーバーフローとアンダーフローは、浮動小数点演算の結果が表現可能な範囲外にある場合に発生します。IEEE 754は両方のケースについて特定の動作を定義しています。
オーバーフロー:
結果の絶対値が最大の表現可能な有限値を超えた場合に発生します。
| 精度 | 最大有限値 | Hex |
|---|---|---|
| Float32 | 3.4028235e+38 |
0x7F7FFFFF |
| Float64 | 1.7976931e+308 |
0x7FEFFFFFFFFFFFFF |
オーバーフローが発生すると、デフォルトの丸めモードでは結果は+Infinityまたは-Infinity(符号による)になります。
一般的なオーバーフローシナリオ:
- 指数的成長:
Math.exp(1000)→Infinity - 大きな乗算:
1e200 * 1e200→Infinity - 二乗:
(1e200) ** 2→Infinity
アンダーフロー:
結果が正規化数として表現するには小さすぎる(ゼロに近すぎる)場合に発生します。IEEE 754は非正規化数による段階的アンダーフローでこれを処理します。
| 精度 | 最小正規化 | 最小非正規化 |
|---|---|---|
| Float32 | 1.175e-38 |
1.401e-45 |
| Float64 | 2.225e-308 |
5e-324 |
最小の非正規化値以下では、結果はゼロにフラッシュされます。
オーバーフローとアンダーフローの検出:
// オーバーフロー検出
if (!isFinite(result)) {
console.log("オーバーフローが発生");
}
// アンダーフロー検出(近似)
if (result !== 0 && Math.abs(result) < Number.MIN_VALUE) {
console.log("結果は非正規化(アンダーフロー)");
}
実際にオーバーフローを避ける:
一般的な手法は対数空間で作業することです。a * bを計算する代わりに、log(a) + log(b)を計算します。精度を犠牲にしてオーバーフローを防ぎます。機械学習フレームワークは確率計算でこれを広く使用しています。
ユースケース
オーバーフローとアンダーフローの管理は、科学計算(粒子物理シミュレーション、宇宙論的計算)、機械学習(損失関数計算、softmax)、金融リスクモデル、および非常に大きなまたは非常に小さな数を扱うアプリケーションに不可欠です。