コンピュータで数値計算を実施する場合に、誤差が生じることがある。いま、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} 程度のずれがあります。これは各ステップの丸め誤差が累積した結果です。 このように、有限ビット数での近似表現によって生じる「丸め誤差」が、加算過程で蓄積されていることが視覚的に確認できます。