やっぱJavaより早い気がするw
今回は積分のプログラミング方法3パターンの比較を行って、収束具合、正確性を見ていく
積分の計算種類
\begin{eqnarray}
\int_a^b f(x) dx
\end{eqnarray}
=\lim_{n \to \infty} \sum^n_{i=0}f(x)\Delta x
基本的に積分は上記式のように区分求積法で計算していくわけだけど、「n \to \infty」はプログラムでは実現できない。なので、様々な計算法で近似して数値解を求める必要がある。
- 長方形近似 一番基本形。積分する領域を長方形に切り刻んで全部足す方法
- 台形近似 長方形近似の上位互換。積分する領域を台形に刻むことで、勾配を配慮した形
- シンプソンの公式 f(x) を二次関数 P(x) で近似する数値解析方法
・数式 \begin{eqnarray} \int_a^b f(x) dx \end{eqnarray} =\sum^n_{i=a}f(i)\Delta x
x座標の始点、終点、ループ回数を引数にした関数だとこんな感じ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FUNCTION SEKIBUN1(UP, BOTTOM, N) | |
F(x) = 4 / (1 + x ** 2) | |
real SUM, BOTTOM, UP, dx | |
INTEGER N | |
SUM = 0.0 | |
dx = (UP - BOTTOM) / N | |
do 10 i = 0, N | |
x = dx * i + BOTTOM | |
SUM = SUM + F(x) * dx | |
10 continue | |
SEKIBUN1 = SUM | |
RETURN | |
END |
・数式 \begin{eqnarray} \int_a^b f(x) dx \end{eqnarray} =\sum^n_{i=a}\frac{f(i)+f(i+\Delta x)}{2}\Delta x
x座標の始点、終点、ループ回数を引数にした関数だとこんな感じ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FUNCTION SEKIBUN2(UP,BOTTOM,N) | |
F(x) = 4 / (1 + x**2) | |
real SUM, BOTTOM, UP, dx | |
INTEGER N | |
SUM = 0.0 | |
dx = (UP - BOTTOM)/ N | |
do 11 i = 0, N | |
x = dx * i + BOTTOM | |
SUM = SUM + (F(x) + F(x + dx))* 0.5 * dx | |
11 continue | |
SEKIBUN2 = SUM | |
RETURN | |
END |
・数式 \begin{eqnarray} \int_a^b f(x) dx \end{eqnarray} =\frac{h}{3}\Bigl\{f(a)+4\sum^m_{i=1}f(x_{2i-1})+2\sum^{m-1}_{i=1}f(x_{2i})+f(b)\Bigr\}
x座標の始点、終点、ループ回数を引数にした関数だとこんな感じ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FUNCTION SEKIBUN3(UP,BOTTOM,N) | |
F(x) = 4 / (1 + x**2) | |
real SUM, BOTTOM, UP, dx | |
INTEGER N | |
dx = (UP - BOTTOM)/ N | |
sum = F(BOTTOM) + F(top) | |
do i = 1, N | |
if(MOD(i, 2).EQ.0) then | |
sum = sum + 4 * F(BOTTOM + i * dx) | |
else | |
sum = sum + 2 * F(BOTTOM + i * dx) | |
end if | |
end do | |
sum = sum * dx / 3.0 | |
SEKIBUN3 = SUM | |
RETURN |
積分の比較
次に3つの積分方法の正確性、収束性、計算スピードについてみていく- 正確性 下記式の左辺の数値解をそれぞれを求め、\piにどれだけ近づくか見てみる \begin{eqnarray} \int_0^1 \frac{4}{1+x^2} dx \end{eqnarray} =\pi
- 収束性 解の収束度合はどうだろうか。
- 計算スピード 最後に計算速度の差について
計算方法 | 解析解 | 正確性[%] |
---|---|---|
長方形近似 | 3.17157602 | 100.9544002 |
台形近似 | 3.16147637 | 100.6329184 |
シンプソンの公式 | 3.15489316 | 100.4233683 |
x軸に刻み回数、y軸に数値解とし、刻み回数と解の収束をグラフ化した
sekibun1→長方形近似、sekibun2→台形近似、sekibun3→シンプソンの公式、pi→\pi 収束度合の数値化がちょっとできてないけど、シンプソンの公式がかなり早い段階で収束することがわかる。
この程度なら差を感じないけど、計算に一週間かかる場合とかだと重要になってくる。それぞれのアルゴリズムの計算回数からだいたいの計算時間のオーダーを求める
f(x)の計算ステップがF、分割数Nとすると
計算方法 | オーダー |
---|---|
長方形近似 | N(4+F) |
台形近似 | N(6+2F) |
シンプソンの公式 | N(6+F) |
つまり、長方形近似>シンプソンの公式>台形近似の順で早いことになる。
特にf(x)の計算ステップが異常にかかる系だと、台形近似が大変
結論
シンプソンの公式が収束率、計算速度が優れていてよさげでも、実装が一番楽な長方形近似で分割数を膨大に増やして計算するのが、実装ミス、手間が省けて効率いいかも思った
以上