基本情報技術者試験の令和7年度の公開問題を解こう。
今回のテーマは、「浮動小数点形式で表現された数値の演算結果における丸め誤差」である。
問2 浮動小数点形式で表現された数値の演算結果における丸め誤差の説明はどれか。
ア 演算結果がコンピュータの扱える最大値を超えることによって生じる誤差である。
イ 数表現のけた数に限度があるので,最下位けたより小さい部分について四捨五入や切上げ,切捨てを行うことによって生じる誤差である。
ウ 乗除算において,指数部が小さい方の数値の仮数部の下位部分が失われることによって生じる誤差である。
エ 絶対値がほぼ等しい数値の加減算において,上位の有効数字が失われることによって生じる誤差である。
正解:イ
浮動小数点形式は、次の形で表す。
例:
| パーツ | 役割 |
|---|---|
| 符号(sign) | 正 or 負 |
| 仮数部(mantissa) | 数字の本体 |
| 指数部(exponent) | 小数点をどこに“浮かせる”か示す |
例として、次の2進数の浮動小数点を考える。
- 符号:+
- 仮数部:1.110100101₂(有効数字)
- 指数部:3(倍する 2 の指数)
「浮動」とは、小数点の位置が「固定」ではなく「指数部によって動く(浮く)」ことである。
同じ 8 ビットの仮数部でも
- 1.00000000 × 2⁰ = 1
- 1.00000000 × 2¹⁰ = 1024
- 1.00000000 × 2⁻¹⁰ = 0.000976…
のように 非常に大きい数~非常に小さい数まで表現可能になる。
ア:誤り。
オーバーフローによる誤差
- コンピュータが扱える最大値より大きい結果が出たときに発生
- 例:「1.0e308 × 1000」のように天文学的な値になってしまう
- これは丸め誤差ではなくオーバーフロー誤差である。
イ:正しい。
浮動小数点は有限の桁数で小数を表すため、表しきれない部分を 四捨五入・切り捨て・切り上げ してしまう。
(例)10進数0.2 は 2進数にすると無限小数になり、仮数部に入りきらない部分が切り捨てられる。
2進小数への変換は、2を掛けて、整数部分を順に取り出す方式で行う。
| step | 計算 | 整数部分 | 小数部分 |
|---|---|---|---|
| 1 | 0.2 × 2 = 0.4 | 0 | 0.4 |
| 2 | 0.4 × 2 = 0.8 | 0 | 0.8 |
| 3 | 0.8 × 2 = 1.6 | 1 | 0.6 |
| 4 | 0.6 × 2 = 1.2 | 1 | 0.2 |
| 5 | 0.2 × 2 = 0.4 | 0 | 0.4 |
| 6 | 0.4 × 2 = 0.8 | 0 | 0.8 |
| 7 | 0.8 × 2 = 1.6 | 1 | 0.6 |
| 8 | …(以下同じ) | … | … |
取り出した整数部分を並べると、
0.2(10) = 0.0011001100110011…(2) (0011 が循環)このように、表現の限界から桁を丸めたときに起きる誤差が丸め誤差である。
ウ:誤り。
情報落ちによる誤差
乗算・除算で指数の桁合わせを行うときに小さい数の下位ビットが消えてしまう誤差
(例)
A = 1.234567 × 10^5
B = 3.21 × 10^1| 項目 | A | B |
|---|---|---|
| 元の値 | 1.234567 × 10^5 | 3.21 × 10^1 |
| 指数をそろえる | 1.234567 × 10^5 | 0.000321 × 10^5 |
| 浮動小数点の仮数部の桁数(例:6桁) | 1.23456(6桁に丸め) | 0.00032 → 6桁に収まらないので切り捨て ⇒ 0.00000 |
| 実際に加算される値 | 1.23456 × 10^5 | 0.00000 × 10^5 |
| 結果 | 1.23456 × 10^5 | (B が完全に消えた) |
※丸め誤差とは別のカテゴリ
エ:誤り。
桁落ちによる誤差
ほぼ等しい数の引き算で起きる。
(例)
(A)1.110100101₂ × 2³
− (B)1.110100010₂ × 2³
---------------------------------
(1.110100101 − 1.110100010) × 2³
=0.000000011₂ × 2³ 正規化すると結果は 1.1₂ × 2⁻⁵(桁を揃えて 1.100000000₂ × 2⁻⁵)になる。
有効数字の桁数が10桁から2桁に減少している。
以下で確認しよう。
- 仮数差(そのままの仮数引き算)
1.110100101₂ − 1.110100010₂ = 0.000000011₂ - 指数を掛ける(元の両数は ×2³)
0.000000011₂ × 2³ = 0.000011₂ - 正規化(先頭が 1 になるように左へシフト)
0.000011₂ = 1.1₂ × 2⁻⁵
仮数長に合わせて表記:1.100000000₂ × 2⁻⁵ (例えば仮数部を9ビットで表示) - 10進数で確かめると
1.1₂ × 2⁻⁵ = (1 + 1/2) × 2⁻⁵ = 1.5 × 1/32 = 0.046875
元の値の差(14.578125 − 14.53125 = 0.046875)と一致する。
Aの10進数変換
仮数部 1.110100101₂ を 10進数へ
1.110100101₂
= 1
+ 1/2
+ 1/4
+ 0/8
+ 1/16
+ 0/32
+ 0/64
+ 1/128
+ 0/256
+ 1/512
=1 + 0.5 + 0.25 + 0 + 0.0625 + 0 + 0 + 0 + 0.0078125 + 0 + 0.001953125
=1.822265625これを 2³(=8)倍すると、
A = 1.822265625 × 8
= 14.578125Bの10進数変換
仮数部 1.110100010₂ を 10進数へ
1.110100010₂
= 1
+ 1/2
+ 1/4
+ 0/8
+ 1/16
+ 0/32
+ 0/64
+ 0/128
+ 1/256
+ 0/512
=1 + 0.5 + 0.25 + 0 + 0.0625 + 0 + 0 + 0 + 0.00390625 + 0
=1.816406252³(=8)掛けると、
B = 1.81640625 × 8
= 14.53125差を計算
A − B = 14.578125 − 14.53125 = 0.046875(ポイント)
元の値はどちらも大きな(≈1.x × 2³)数だったのに、引き算の結果は指数が大きく変わり(2³ → 2⁻⁵)、上位桁が打ち消されて 桁落ち(catastrophic cancellation) が起きている。有限ビットの浮動小数点でこの結果を表現するとき、正規化後の仮数(ここでは 1.1…) の下位ビットがさらに切り捨てられやすく、相対誤差が大きくなる。


コメント