sp-13. 数値微分と数値積分
1
金子邦彦
Scheme プログラミング)
URL: https://www.kkaneko.jp/pro/scheme/index.html
数値微分と数値積分の原理を理解し、Schemeで実
装する技法の習得
【学習内容の構成】
1. 数値微分(d/dx:接線の傾きを差分商で近似
する手法
2. 台形則(trapezoid:小台形の面積の総和で定
積分を近似する手法
3. 高階関数:関数を引数として受け取る関数の定
義と活用
前提:Schemeの基本文法、関数定義、再帰
意義:解析的に積分できない関数への対処法の獲
得、近似計算における精度と計算コストのトレー
ドオフの理解
2
13-1 数値微分と数値積分
3
1. 接線の傾き d/dx
2. 台形則による数値積分 trapezoid
内容
4
5
接線の傾き
h 0 に近づけることで、接線の傾き
(=f '(x) )の「近似値」が求まる
h
hxfhxf
+
2
)()(
x
f(x)
0
hx
hx +
)( hxf
)( hxf +
傾きは
接線
区間 [a, b] で,連続関数 f, x,
x=a, x=b で囲まれた面積
f(x)
a
b
x
=
b
a
dxxfI )(
定積分:
定積分
6
n 個の等間隔な小区間に分割
幅: h = (b-a) / n
小区間: [x
0
, x
1
], [x
1
, x
2
], ..., [x
n-1
, x
n
]
但し,x
0
= a, x
i
= x
0
+ i × h
f(x)
x
0
= a
x
n
= b
x
x
1
x
2
x
n-1
区間 [a, b] の小区間への分割
7
小長方形の面積は
f(x)
x
0
= a
x
n
= b
x
x
i
x
i+1
小長方形
f(x
i
)
hxf
i
)(
小長方形
8
小台形の面積は
f(x)
x
0
= a
x
n
= b
x
x
i
x
i+1
小台形
f(x
i
)
f(x
i+
1
)
小台形
9
小台形の面積の和は
定積分 I を,この和 S
n
で近似 台形則という
f(x)
x
0
= a
x
n
= b
x
))()((
2
1
1
0
+
=
+=
ii
n
i
n
xfxf
h
S
x
1
x
2
x
n-1
x
3
x
n-2
台形則 trapezoidal rule
10
区間[ab]を n 等分 (1区間の幅h=(b-a)/n)
n 個の台形を考え, その面積の和 S
n
で,定積分 I を近
f(x) が連続関数のときは,n を無限大に近づければ,S
n
I
に近づく
但し,単純に「n を大きくすればよい」とは言えない
n を大きくすると 計算時間の問題,丸め誤差の問題が
発生
n
n
ii
n
i
n
Sxfxf
h
I
+
=
=+=
lim))()((
2
lim
1
1
0
台形則による数値積分
11
式で書いてある関数の積分
ごく限られた関数しか定積分できない
「数値積分」が重要になる
数値積分の意味
12
両端 x
0
= a x
n
= b を除いて,f(x
i
) は2度現
れる
( )
)()(
2
1
1
0
+
=
+=
ii
n
i
n
xfxf
h
S
( )
)())()((2)(
2
110 nn
xfxfxfxf
h
++++=
但し h = (b-a) / n
2回現れる部分
++=
=
)(
2
1
)()(
2
1
1
1
0 n
n
i
i
xfxfxfh
+++=
=
)(
2
1
)()(
2
1
1
1
bfihafafh
n
i
台形則
13
13-2 パソコン演習
14
資料を見ながら,「例題」を行ってみる
各自,「課題」に挑戦する
自分のペースで先に進んで構いません
パソコン演習の進め方
15
DrScheme の起動
プログラム PLT Scheme
DrScheme
今日の演習では「Advanced Student
に設定
Language
→ Choose Language
Advanced Student
→ OK
Execute ボタン」
DrScheme の使用
16
接線の傾きを求める関数 d/dx を作り,
実行する
数値 x, h と関数 f から,x における f
傾き(= f' (x))の近似値を求める
d/dx は高階関数
例題1.接線の傾き
17
1. 次を「定義用ウインドウ」で,実行しなさい
入力した後に,Execute ボタンを押す
;; d/dx: (number->number) number number -> number
;; inclination of the tangent
;; Example: (d/dx f 3 0.0001)
;; = ((- (f 3.0001) (f 2.9999)) 0.0002)
(define (d/dx f x h)
(/ (- (f (+ x h)) (f (- x h)))
(* 2 h)))
(define (f2 x)
(- (* x x) 2))
2. その後,次を「実行用ウインドウ」で実行しなさい
次は,例題2に進んでください
(d/dx f2 3 0.0001)
「例題1.接線の傾き」の手順
18
まず,関数 d/dx を定義している
19
次に関数 f2 を定義している
(define (f2 x)
(- (* x x) 2))
20
これは,
(d/dx f2 3 0.0001)
と書いて,x の値を 3 ,
h の値を 0.0001 に,
f f2 に設定しての実行
実行結果である「6」が
表示される
21
d/dx
f2'(3) の近似値
入力
出力
f2
3
0.0001
入力は2つの数値と
関数
出力は数値
d/dx は,関数を入力とするような関数
(つまり高階関数)
入力と出力
22
;; d/dx: (number->number) number number -> number
;; inclination of the tangent
;; Example: (d/dx f 3 0.0001)
;; = ((- (f 3.0001) (f 2.9999)) 0.0002)
(define (d/dx f x h)
(/ (- (f (+ x h)) (f (- x h)))
(* 2 h)))
関数が,
d/dx」の入力になっている
d/dx 関数
23
(dx/d f2 3 0.0001) から 6 が得られる過程の概略
(dx/d f2 3 0.0001)
= (/ (- (f2 (+ 3 0.0001)) (f2 (- 3 0.0001)))
(* 2 0.0001))
= (/ (- (- (* (+ 3 0.0001) (+ 3 0.0001)) 2)
(- (* (- 3 0.0001) (- 3 0.0001)) 2)
(* 2 0.0001)))
= …
= 6
最初の式
実行結果
コンピュータ内部での計算
但し,f2
(define (f2 x)
(- (* x x) 2))
24
(dx/d f2 3 0.0001) から 6 が得られる過程の概略
(dx/d f2 3 0.0001)
= (/ (- (f2 (+ 3 0.0001)) (f2 (- 3 0.0001)))
(* 2 0.0001))
= (/ (- (- (* (+ 3 0.0001) (+ 3 0.0001)) 2)
(- (* (- 3 0.0001) (- 3 0.0001)) 2)
(* 2 0.0001)))
=
= 6
これは,
(define (d/dx f x h)
(/ (- (f (+ x h)) (f (- x h)))
(* 2 h)))
x 3 で,h 0.0001 , f f2 で置き換
えたもの
25
(dx/d f2 3 0.0001) から 6 が得られる過程の概略
(dx/d f2 3 0.0001)
= (/ (- (f2 (+ 3 0.0001)) (f2 (- 3 0.0001)))
(* 2 0.0001))
= (/ (- (- (* (+ 3 0.0001) (+ 3 0.0001)) 2)
(- (* (- 3 0.0001) (- 3 0.0001)) 2)
(* 2 0.0001)))
= …
= 6
これは,
(define (f2 x)
(- (* x x) 2))
x (+ 3 0.0001) (- 3 0.0001) で置き換えたも
26
台形則による数値積分の関数
trapezoid を作り,実行する
但し,
積分したい関数 f(x) = e
積分区間: [a, b]
区間数: n
-x
2
例題2.台形則による数値積分
27
1. 次を「定義用ウインドウ」で,実行しなさい
入力した後に,Execute ボタンを押す
(define (trapezoid-iter f a h k)
(cond
[(= k 1) (f (+ a h))]
[else (+ (f (+ a (* h k)))
(trapezoid-iter f a h (- k 1)))]))
;; trapezoid: number number number -> number
;; to compute the area under the graph of f between a and b
(define (trapezoid f a b n)
(* (/ (- b a) n)
(+ (trapezoid-iter f
a
(/ (- b a) n)
(- n 1))
(/ (f a) 2)
(/ (f b) 2))))
(define (f2 x)
(exp (- (* x x))))
2. その後,次を「実行用ウインドウ」で実行しなさい
次は,課題に進んでください
(trapezoid f2 0 1 1000)
「例題2.台形則による数値積分」の手順
28
まず,関数 trapezoid-iter,
trapezoid を定義している
29
次に関数 f2 を定義している
(define (f2 x)
(exp (- (* x x))))
これは,数値積分したい関数
30
これは,
(trapezoid f2 0 1 1000)
と書いて,a の値を 0 ,
b の値を 1 に,h の値を 1000 に,
f f2 に設定しての実行
実行結果である
#i0.7468240714991842
が表示される
31
(define (trapezoid-iter f a h k)
(cond
[(= k 1) (f (+ a h))]
[else (+ (f (+ a (* h k)))
(trapezoid-iter f a h (- k 1)))]))
;; trapezoid: number number number -> number
;; to compute the area under the graph of f between a
and b
(define (trapezoid f a b n)
(* (/ (- b a) n)
(+ (trapezoid-iter f
a
(/ (- b a) n)
(- n 1))
(/ (f a) 2)
(/ (f b) 2))))
32
例題2での台形則の計算の精度が,分割幅を小さ
くするほど高精度になることを確かめる.
但し,
積分したい関数 f(x) = e
積分区間 0 から 1
分割数 10, 20, 40, 80, 160, 320, 640, 1280 の8通り
-x
2
例題3.台形則の計算の精度
33
1. 次を「定義用ウインドウ」で,実行しなさい
入力した後に,Execute ボタンを押す
(define (trapezoid-iter f a h k)
(cond
[(= k 1) (f (+ a h))]
[else (+ (f (+ a (* h k)))
(trapezoid-iter f a h (- k 1)))]))
;; trapezoid: number number number -> number
;; to compute the area under the graph of f between a and b
(define (trapezoid f a b n)
(* (/ (- b a) n)
(+ (trapezoid-iter f
a
(/ (- b a) n)
(- n 1))
(/ (f a) 2)
(/ (f b) 2))))
(define (f2 x)
(exp (- (* x x))))
これは,例題2と同じ
例題3.「台形則の計算の精度」の手順 (1/2)
34
次は,課題に進んでください
(trapezoid f2 0 1 10)
(trapezoid f2 0 1 20)
(trapezoid f2 0 1 40)
(trapezoid f2 0 1 80)
(trapezoid f2 0 1 160)
(trapezoid f2 0 1 320)
(trapezoid f2 0 1 640)
(trapezoid f2 0 1 1280)
2. その後,次を「実行用ウインドウ」で実行
しなさい
例題3.「台形則の計算の精度」の手順(2/2)
35
分割幅を小さくするほど高精度
数値積分の精度
36
近似値を求める手法
数値微分,数値積分
十分に役に立つ
「必ず誤差が生じる」ことを意識しながら使うことが
必要
おわりに
37
13-3 課題
38
f(x) = x cos x について,f'(0), f'(0.2),
f'(0.4), f'(0.6) の値を報告しなさい
関数 d/dx (授業の例題1)を使いなさい
h = 0.1 としなさい
課題1
39
f(x) = x cos x について,h = 0.1, 0.01,
0.001 と変えて関数 d/dx を実行し,結
果を比べなさい
h と誤差の関係が分かるグラフを作成せ
演習2
40
台形則を使って,次を計算せよ
計算結果を,以下と比較せよ
+
=
1
0
1
2log dx
x
x
e
DrScheme での (log 2) の実行結果
演習3
41
演習3について,区間数 n を,n = 4, 8, 16,
32, 64, 128 と変えて計算を行い,刻み幅と誤
差の関係を調べよ
区間数 n と誤差の関係を書いたグラフを作成せよ
この場合,おおよそ次の関係が成り立っているこ
とを確認せよ
2
n
c
ISn
c は定数)
演習4
42
関数 d/dx (例題1)を使って,関数
のグラフをグラフィックスで表示させ
なさい
プログラムは次ページ以降にある.この
プログラムを実行させ,実行結果を報告
しなさい
但し,実行結果の報告では,必 関数
f2 を別のものに書き換えて実行しなさい
演習4.関数のグラフ
43
;; d/dx: (number->number) number number -> number
;; inclination of the tangent
;; Example: (d/dx f 3 0.0001)
;; = ((- (f 3.0001) (f 2.9999)) 0.0002)
(define (d/dx f x h)
(/ (- (f (+ x h)) (f (- x h)))
(* 2 h)))
;; samples: (number->number) number number number -> list of
'posn' structure
(define (samples f a h k)
(cond
[(= k 1) (cons (make-posn (+ a h)
(f (+ a h)))
empty)]
[else (cons (make-posn (+ a (* h k))
(f (+ a (* h k))))
(samples f a h (- k 1)))]))
44
; window size
(define WX 500)
(define WY 500)
; grid color, axis color and
(define GRID_COLOR 'blue)
(define AXIS_COLOR 'red)
(define GRAPH_COLOR 'red)
; draw-a-line
(define (sessen x px py d)
(+ (* d (- x px)) py))
(define (draw-a-sessen from to px py d x0 y0 sx sy)
(draw-solid-line (make-posn (+ (* from sx) x0) (+ (* (sessen from px py d) sy)
y0))
(make-posn (+ (* to sx) x0) (+ (* (sessen to px py d) sy) y0))
GRAPH_COLOR))
(define (draw-sessen f px x0 y0 sx sy)
(draw-a-sessen (/ (- x0) sx) (/ (- WX x0) sx) px (f px) (d/dx f px 0.00001) x0
y0 sx sy))
45
; draw-polyline
(define (draw-polyline a-poly)
(cond
[(empty? (rest a-poly)) true]
[else (and
(draw-solid-line (first a-poly)
(first (rest a-poly)) GRAPH_COLOR)
(draw-polyline (rest a-poly)))]))
; draw-h-lines
(define (draw-h-lines start skip stop width)
(cond
[(>= start stop)
(draw-solid-line (make-posn 0 stop) (make-posn width stop)
GRID_COLOR)]
[else
(and
(draw-solid-line (make-posn 0 start) (make-posn width start)
GRID_COLOR)
(draw-h-lines (+ start skip) skip stop width))]))
46
; draw-v-lines
(define (draw-v-lines start skip stop height)
(cond
[(>= start stop)
(draw-solid-line (make-posn stop 0) (make-posn stop height)
GRID_COLOR)]
[else
(and
(draw-solid-line (make-posn start 0) (make-posn start height)
GRID_COLOR)
(draw-v-lines (+ start skip) skip stop height))]))
; (x0, y0) is the origin. sx and sy represent one grid size
(define (draw-grid x0 y0 sx sy)
(and
(draw-v-lines (- x0 (* (quotient x0 sx) sx)) sx (+ (* (quotient (- WX x0) sx) sx)
x0) WY)
(draw-h-lines (- y0 (* (quotient y0 sy) sy)) sy (+ (* (quotient (- WY y0) sy) sy)
y0) WX)
(draw-solid-line (make-posn 0 y0) (make-posn WX y0) AXIS_COLOR)
(draw-solid-line (make-posn x0 0) (make-posn x0 WY) AXIS_COLOR)))
47
; (x0, y0) is the origin. sx and sy represent one grid size
(define (scaling a-list x0 y0 sx sy)
(cond
[(empty? a-list) empty]
[else (cons (make-posn (+ (* (posn-x (first a-list)) sx) x0)
(+ (* (posn-y (first a-list)) sy) y0))
(scaling (rest a-list) x0 y0 sx sy))]))
;
; f2: number -> number
(define (f2 x)
(- (* x x) 2))
; (X0, Y0) reprerents the origin of the graph.
; SX and SY represent the size of one grid
(define X0 (/ WX 2))
(define Y0 (/ WY 2))
(define SX 50)
(define SY 50)
(define PX 0.5)
(start WX WY)
(draw-grid X0 Y0 SX SY)
(draw-polyline (scaling (samples f2 (/ (- X0) SX) (/ 1 SX) WX) X0 Y0 SX SY))
(draw-sessen f2 PX X0 Y0 SX SY)
48