コンピュータで数値計算を実施する場合に、誤差が生じることがある。いま、0.01をコンピュータ内部で表現した値を100回足したところ答えが1にはならなかった。プログラム自体に誤りは無いとすると、1にならなかった原因の誤差として最も適切なものはどれか。なお、コンピュータ内部では数値を2進数で扱っており、0.01は2進数では循環小数で表現するものとする。
  • 桁落ち
  • 情報落ち
  • オーバーフロー
  • アンダーフロー
  • 丸め誤差

https://kakomonn.com/gijyutushi/questions/36506

この現象は 丸め誤差 によるものです。

コンピュータは小数を有限ビットの2進数でしか表現できないため、10進数の 0.01 は2進で循環小数になります。

循環小数を有限ビットで切り捨て・四捨五入して近似表現する際に生じる誤差が「丸め誤差」です。

この近似値を100回足し合わせると、各回のわずかな誤差が累積し、厳密に1.00にはならず 0.9999… や 1.0000… のわずかにずれた値になります。

他の選択肢との違い:

桁落ち:ほぼ同じ大きさの数同士の引き算で有効桁が失われる現象。今回の加算では該当しません。

情報落ち(=アンダーフロー):非常に小さな値がゼロに丸め込まれる現象。0.01×100では起こりません。

オーバーフロー:表現可能な最大値を超えてしまう現象。今回の例では桁も値も十分小さいので無関係です。

したがって、最も適切なのは 丸め誤差 です。

0.01を2進数で表してください

0.01₁₀ = 0.000000101000111101011100001010…₂
ビット列を求める手順は次のとおりです:

0.01 × 2 = 0.02 → 整数部 0

0.02 × 2 = 0.04 → 整数部 0

0.04 × 2 = 0.08 → 整数部 0

0.08 × 2 = 0.16 → 整数部 0

0.16 × 2 = 0.32 → 整数部 0

0.32 × 2 = 0.64 → 整数部 0

0.64 × 2 = 1.28 → 整数部 1(余り 0.28)

0.28 × 2 = 0.56 → 整数部 0

0.56 × 2 = 1.12 → 整数部 1(余り 0.12)

0.12 × 2 = 0.24 → 整数部 0

0.24 × 2 = 0.48 → 整数部 0

0.48 × 2 = 0.96 → 整数部 0

0.96 × 2 = 1.92 → 整数部 1(余り 0.92)
…以降同様に繰り返し

こうして得られる小数点以下のビット列が
000000101000111101011100001010…
となり、これをまとめて

0.000000101000111101011100001010…₂
と表記します。

実際に加算されていく様子を見せてください

CSV:0_01________1_100__

上記の表は、0.01 を 1 回から 100 回まで加算した後の結果を示しています。

  • 加算後の値 (10進):実際に浮動小数点演算で得られた十進数の値
  • 加算後の値 (float.hex):内部的な 16 進表現(IEEE754 倍精度)
  • 理論値との差:理論的な i×0.01i\times0.01 との差(ここではほぼ 0 ですが、回数を重ねると微小な差が累積します)

たとえば 100 回加算後の値は 1.0000000000000007(内訳 0x1.0000000000001p+0)で、理論上の 1.00 とは約 7×10167\times10^{-16} 程度のずれがあります。これは各ステップの丸め誤差が累積した結果です。
このように、有限ビット数での近似表現によって生じる「丸め誤差」が、加算過程で蓄積されていることが視覚的に確認できます。