高校数学10分プログラミング(数学Ⅱ編 5.微分法と積分法)1日目「数値微分について考える」
マガジンリスト > 数学Ⅱ編 5.微分法と積分法 > 1日目 課題
おはようございます。
本日は、高校数学10分プログラミング(数学II編 5.微分法と積分法)の1日目です。
本日の課題は、数値微分を行うプログラムを作成することです。
微分係数、導関数
まず、微分係数や導関数などについて解説しておきます。
平均変化率
$$
\frac{f(b)-f(a)}{b-a}
$$
微分係数(変化率)
$$
f'(a) = \lim_{h \to 0} \frac{f(a+h)-f(a)}{h} = \lim_{b \to a} \frac{f(b)-f(a)}{b-a}
$$
導関数
$$
f'(x) = \lim_{h \to 0} \frac{f(x+h)-f(x)}{h}
$$
導関数の公式
① $${n}$$が正の整数のとき $${(x^n)'=n x^{n-1}}$$
② $${c}$$が定数のとき $${(c)' = 0}$$
③ $${k,l}$$が定数のとき $${ \{kf(x)+lg(x) \}' = kf'(x)+lg'(x) }$$
コンピュータで微分する(数値微分)
上記で、微分係数や導関数について解説しましたが、この微分をコンピュータで行うためには1つ問題があります。それは、$${h \to 0}$$や$${b \to a}$$などの極限処理をコンピュータで行うことができないことです。つまり、微分係数や導関数をコンピュータで厳密に計算することは難しいです。そこで、コンピュータで微分する場合、差分という処理で近似します。考え方は単純で、$${h \to 0}$$のような極限を取る代わりに、小さな正の値をもつ$${h (\ll 1)}$$に対して、
$$
\frac{f(a+h)-f(a)}{h} \mathrm{や} \frac{f(x+h)-f(x)}{h}
$$
を計算することで微分係数や導関数を近似するということを行います。この処理を数値微分と呼びます。
数値微分の方法としては、大きく3つの方法があります。順に紹介していきます。
前方差分
1つ目は前方差分です。
図1を見てください。青色の直線は関数$${f(x)}$$の$${x=a}$$での接線で、この接線の傾きが$${x=a}$$での微分係数$${f'(a)}$$となります。この微分係数$${f'(a)}$$を求めたいのですが、先ほども説明した通り、コンピュータでの極限処理が難しいので、厳密に$${f'(a)}$$を求めることはできません。
そこで、赤色の直線のように、$${x=a}$$での$${y=f(x)}$$のグラフ上の点$${(a, f(a))}$$と$${x=a}$$より少し前方の$${x=a+h}$$での点$${(a+h, f(a+h))}$$と結ぶ直線を考え、その直線の傾きを$${f'(a)}$$の近似値とします。
$$
f'(a) \approx \frac{f(a+h)-f(a)}{h}
$$
これを前方差分と呼びます。
後方差分
次に、後方差分です。
図2の赤色の直線を見てください。$${x=a}$$での$${y=f(x)}$$のグラフ上の点$${(a, f(a))}$$と$${x=a}$$より少し後方の$${x=a-h}$$での点$${(a-h, f(a-h))}$$と結ぶ直線を考え、その直線の傾きを$${f'(a)}$$の近似値とします。
$$
f'(a) \approx \frac{f(a)-f(a-h)}{h}
$$
これを後方差分と呼びます。
中心差分
最後は、中心差分です。
図3の赤色の直線を見てください。$${x=a}$$より少し後方の$${x=a-h/2}$$での点$${(a-h/2, f(a-h/2))}$$と$${x=a}$$より少し前方の$${x=a+h/2}$$での点$${(a+h/2, f(a+h/2))}$$と結ぶ直線を考え、その直線の傾きを$${f'(a)}$$の近似値とします。
$$
f'(a) \approx \frac{f(a+h/2)-f(a-h/2)}{h}
$$
これを後方差分と呼びます。
課題
$${f(x)=3x^2+2x+1}$$について、次の微分係数の値を真値と共に、前方差分、後方差分、中心差分の3種類で数値微分して求めるプログラムを作成してください。また、それらの結果を比較してみてください。
(1) $${f'(0)}$$
(2) $${f'(1)}$$
(3) $${f'(-1)}$$
(4) $${f'(2)}$$
ヒント
プログラム
微分係数の真値と3つの数値微分の結果を比較するためのプログラム(未完成)を示します(ソースコード1)。
// 数値微分の精度比較
void setup(){
float h = 0.001; // 差分の大きさ
// (1) f'(0)
float a = 0.0;
float exact = f_prime(a);
float front = front_diff(a,h);
float back = back_diff(a,h);
float central = central_diff(a,h);
println("(1):", exact, "前方差分:", front, "後方差分:", back, "中心差分:", central);
// (2) f'(1)
a = 1.0;
exact = f_prime(a);
front = front_diff(a,h);
back = back_diff(a,h);
central = central_diff(a,h);
println("(2):", exact, "前方差分:", front, "後方差分:", back, "中心差分:", central);
// (3) f'(-1)
a = -1.0;
exact = f_prime(a);
front = front_diff(a,h);
back = back_diff(a,h);
central = central_diff(a,h);
println("(3):", exact, "前方差分:", front, "後方差分:", back, "中心差分:", central);
// (4) f'(2)
a = 2.0;
exact = f_prime(a);
front = front_diff(a,h);
back = back_diff(a,h);
central = central_diff(a,h);
println("(4):", exact, "前方差分:", front, "後方差分:", back, "中心差分:", central);
}
// f(x) =3x^2+2x+1
float f(
float x
){
return 3.0*x*x+2.0*x+1.0;
}
// f'(x)
float f_prime(
float x
){
return
}
// 前方差分
float front_diff(
float a,
float h // 差分の大きさ
){
return
}
// 後方差分
float back_diff(
float a,
float h // 差分の大きさ
){
return
}
// 中心差分
float central_diff(
float a,
float h // 差分の大きさ
){
return
}
ソースコード1 微分係数の真値と3つの数値微分の結果を比較するためのプログラム(未完成)
ソースコード1では、元の関数$${f(x)}$$を関数 f 、$${f(x)}$$の導関数を f_prime 関数、前方差分を求める関数 front_diff 、後方差分を行う関数 back_diff 、中心差分を行う関数 central_diff としてそれぞれ準備し、setup 関数内でこれらの関数を呼び出すことでそれぞれの微分係数の値を求めるようにしています。
ただし、4つの関数 f_prime 、front_diff 、back_diff 、central_diff は返り値をまだ記載していません。上記の導関数やコンピュータで微分する(数値微分)の節を参考に、返り値を追記してプログラムを完成させてください。
なお、 スケッチ名は「calcThreeDifferences」とします。
それでは、よろしくお願いします。
MK's papa