二分法による 1 変数方程式の解 Last modified: Apr 13, 2004
目的
二分法により一変数間数 f(x)=0 の解を求める。
R には uniroot という関数もあり,これはおもしろい(有効な)使い方ができる。
使用法
bisection(func, lower, upper, ndiv=50, epsilon=1e-14, max.iteration=500)
引数
fun 関数定義
lower 解を探索する範囲の下限値
upper 解を探索する範囲の上限値
ndiv 解を探索する範囲の区分数(50)
epsilon 許容誤差(1e-14)
max.rotation 収束計算上限界数(500)
ソース
インストールは,以下の 1 行をコピーし,R コンソールにペーストする
source("http://aoki2.si.gunma-u.ac.jp/R/src/bisection.R", encoding="euc-jp")
# 分法により一変数間数 f(x)=0 の解を求める
bisection <- function( func, # 関数 たとえば function(x) (x+6.7)*(x-3.4) のようなもの
lower, upper, # 解を求める区間
ndiv=50, # 区間を細区分する個数
epsilon=1e-14, # 解の許容誤差
max.iteration=500) # 反復回数の上限
{
printf <- function(fmt, ...) cat(sprintf(fmt, ...)) # 書式付きの print
bisec2 <- function(func, lower, upper) # 区間の再区分について解を探索する下請け関数
{
yl <- func(lower) # 区間の左端における関数値
yu <- func(upper) # 区間の右端における関数値
if (yl*yu > 0) { # 同じ符号のとき,この区間には解がない(区間の設定不良)
return(1) # 戻り値として 1 を返す(利用しなくてもよい)
}
for (i in 1:max.iteration) { # 繰り返し上限まで収束計算を続ける
mid <- (lower+upper)/2 # そのときの区間の中点の値
ym <- func(mid) # 中点における関数値
if (abs(ym) < epsilon) { # たまたま解になったら結果を書き出す
printf("ans=%g\n", mid)
return(0)
}
else if (yu*ym > 0) { # 区間の右端での関数値と符号が同じなら,
upper <- mid # 中点を区間の右端にする
yu <- ym # 新しい区間の右端での関数値を設定する
}
else { # 区間の左端での関数値と符号が同じなら,
lower <- mid # 中点を区間の左端にする
yl <- ym # 新しい区間の左端での関数値を設定する
}
if (abs(upper-lower) < epsilon) { # 区間幅が誤差範囲内になったら中点を解とする
printf("ans=%g\n", (lower+upper)/2)
return(0)
}
}
}
x <- seq(lower, upper, length.out=ndiv) # 区間を細区分して,
for (i in 1:(ndiv-1)) { # それぞれの細区分に対して,
bisec2(func, x[i], x[i+1]) # 二分法により解を求める下請け関数を呼ぶ
}
}
使用例
bisection(function(x) (x+6.7)*(x-3.4)*(x-sqrt(2)), -10, 10, ndiv=300) # 3 次方程式の解
出力結果例
> bisection(function(x) (x+6.7)*(x-3.4)*(x-sqrt(2)), -10, 10, ndiv=300)
ans=-6.7
ans=1.41421
ans=3.4
直前のページへ戻る
E-mail to Shigenobu AOKI ( @si.gunma-u.ac.jp )