sum.py テクニカルドキュメント

プログラムの動作

sum.py は、浮動小数点数の加算を繰り返し行うことで発生する累積誤差をシミュレーションするプログラムです。指定された浮動小数点数 \(h\) を指定された回数 \(n\) だけ加算していき、その計算過程と最終結果を表示します。

主な機能は以下の通りです。

  • コマンドライン引数から加算する値 \(h\) と加算回数 \(n\) を受け取ります。

  • \(h\)\(n\) 回累積加算するシミュレーションを実行します。

  • 各ステップでの加算前、加算する値、加算後の値を出力します(\(n\) が小さい場合、またはステップが \(n\) の約数回ごとに)。

  • 最終的な計算結果と、理論値(\(h \times n\))との差分を表示します。

このプログラムは、コンピュータ内部での浮動小数点表現(IEEE 754など)に起因する丸め誤差が、反復計算によってどのように累積していくかを視覚的に理解するための教材として利用されます。

原理

このプログラムの核となる原理は、有限精度で表現される浮動小数点数の加算における誤差の累積です。コンピュータは数値を有限のビット数で表現するため、多くの実数を正確に表現することができません。例えば、\(0.1\)\(0.3\) といった十進小数は、二進数表現では無限小数となり、特定のビット数で「丸め」られることになります。この丸めによって生じる微小な誤差が、繰り返し加算されることで蓄積されていきます。

プログラムは、以下の単純な反復加算アルゴリズムに基づいています。

  1. 初期値 \(a_0 = 0.0\) を設定します。

  2. \(k = 0, 1, \dots, n-1\) について、以下の計算を繰り返します。 $\(a_{k+1} = a_k + h\)\( ここで、\)h$ は加算する値です。

理論上、正確な数学的計算では、\(n\) 回の加算後の結果 \(S_{true}\) は以下のように計算されます。

\[S_{true} = \sum_{i=1}^{n} h = n \times h\]

しかし、コンピュータ上での浮動小数点演算では、各ステップでの加算 \(a_k + h\) の結果が丸められるため、実際の計算結果 \(a_n\)\(S_{true}\) とは異なる場合があります。

最終的にプログラムが表示する「Difference」は、この理論値と実際の計算結果との差であり、累積された浮動小数点誤差の量を示しています。

\[ \text{Difference} = a_n - S_{true} = a_n - (n \times h) \]

この差分は、各加算ステップで発生する小さな丸め誤差が積み重なった結果です。

必要な非標準ライブラリとインストール方法

sum.py プログラムは、Pythonの標準ライブラリである sys のみを使用しており、追加の非標準ライブラリは必要ありません。そのため、特別なインストール作業は不要です。

必要な入力ファイル

sum.py は入力ファイルを必要としません。必要な情報はすべてコマンドライン引数として与えられます。

生成される出力ファイル

sum.py は、ファイルを生成したり保存したりすることはありません。すべての結果は標準出力 (stdout) に表示されます。

コマンドラインでの使用例 (Usage)

sum.py は、コマンドライン引数として加算する浮動小数点数 \(h\) と加算回数 \(n\) を受け取ります。

基本的な実行コマンドの形式は以下の通りです。

python sum.py h n
  • h: 加算する浮動小数点数(例: 0.3, 0.1

  • n: 加算を繰り返す回数を示す整数(例: 100, 1000

引数を省略した場合、プログラムはデフォルト値 (h=0.3, n=1000) を使用し、上記のUsageメッセージを表示します。

コマンドラインでの具体的な使用例

ここでは、h0.3n1000 を与えて実行する例を示します。

python sum.py 0.3 1000

上記のコマンドを実行すると、以下のような出力が標準出力に表示されます。

Parameters:
  h (increment) = 0.3
  n (iterations) = 1000
  Expected result = 300.0
------------------------------
   1: 0.0                  + 0.3 => 0.3
 101: 30.000000000000004   + 0.3 => 30.300000000000004
 201: 60.30000000000001    + 0.3 => 60.60000000000001
 301: 90.60000000000001    + 0.3 => 90.90000000000002
 401: 120.90000000000003   + 0.3 => 121.20000000000003
 501: 151.20000000000005   + 0.3 => 151.50000000000006
 601: 181.50000000000006   + 0.3 => 181.80000000000007
 701: 211.80000000000007   + 0.3 => 212.10000000000008
 801: 242.10000000000008   + 0.3 => 242.4000000000001
 901: 272.4000000000001    + 0.3 => 272.7000000000001
1000: 299.7000000000001    + 0.3 => 300.0000000000001
------------------------------
Final Result: 300.0000000000001
Difference  : 1.1368683772161603e-13

この出力は、以下の内容を示しています。

  • Parameters: 指定された \(h\)\(n\) の値、および理論上の期待結果 (\(h \times n\))。

  • 計算過程: 各ステップ(1回目、\(n/10\) 回目、\(2n/10\) 回目...、最終回)での加算前 (aprev)、加算する値 (h)、および加算後 (a) の値が表示されます。0.31000 回加算しているため、期待される結果は 300.0 です。しかし、途中経過の 30.000000000000004300.0000000000001 のように、厳密な 0.0300.0 からわずかにずれた値が表示されています。これは、浮動小数点数 0.3 が二進数で正確に表現できないために生じる丸め誤差が累積していることを示しています。

  • Final Result: \(n\) 回の加算が完了した後の最終結果。

  • Difference: 最終結果と理論上の期待結果との差分。この例では 1.1368683772161603e-13 という非常に小さいが非ゼロの値が表示されており、浮動小数点数の累積誤差が存在することを確認できます。