二分法とは、f(x) が区間[a; b] 内で連続かつ、f(a) とf(b) の符号が異なる時(計算機的には
f(a) f(b) < 0 と書く)に、方程式f(x) = 0 の解を次のような方法で求める。
- まず、方程式の解は区間[a; b] 内にある。ここで、一つの解の上限をhigh, 下
限をlow という変数に入れる。(これはプログラム的にはf(high) f(low) < 0 の
意味である)初期条件としては、low ( b, high ( a である。
2. 次に、x ( (high+low)=2 と置く。ここで、f(x)f(high) < 0 の時にlow ( x
そうでない時に、high ( x とすると、これは一つの解の上限、下限を表してい
る。この操作を一回繰り返すごとに、解の区間が半分にせばまってくる。
3. 上の操作を何回か繰り返して、low high の値が近くなった時、これを解と思
い、操作を打ち切る。そうでない時は2 に戻る。
/houteisiki01.c/
#include <stdio.h>
#include <math.h>
#define EPS 1e-8 /* 打ち切り誤差*/
#define LIMIT 50 /* 打ち切り回数*/
double f(double x){
return sin(x);
}
double nibun(double (*f)(double), double a, double b){
double x,low,high;
int k=1;
a=low; b=high;
for (k=1;k<=LIMIT;k++) {
x=(low+high)/2;
if (f(high)*f(x)>0) high=x; else low=x;
if (f(x)==0 || fabs(high-low)<EPS) return x;
}
if (k>LIMIT) {printf("収束しない\n"); return 99999;}
}
main(){
printf("x=%lf \n",nibun(f,-4,-3));
}
実行結果
x=-3.141593
上のプログラムでは、sin x = 0 の解をx 2 [????4;????3] の範囲で求めている。こ
のプログラムでは、解の範囲を[????4; 3] のように、sin(????4)(> 0), sin(3)(> 0) のよ
うに両端(a=high, b=low) での関数の値の符号が同じ時には上手く動かない。そ
こで、以下のようなプログラムの改良を考えてみる。
関数f(x), と区間[a; b] が与えられた時、[a; b] 内の点c でf(a) f(c) < 0 で
あるものを見つける関数ryotan は以下のように作れる。
double ryotan(double (f)(double), double a, double b){
int n=1,i;
double x,atai;
atai=f(a);
while(n<=1024){
for(i=1;i<=n;i++){
x=a+(b-a)i/n;
if (ataif(x)<0) return x;
}
n=n2;
}
if(atai>0) {printf("f(x)>0 です.\n"); return 9999;}
if(atai<0) {printf("f(x)<0 です.\n"); return 9999;}
}
問い:houteisiki02.c 上の関数ryotan を使って、2 分法のプログラムが、f(a)
f(b) > 0 の時も(解がある場合は)動くように改良せよ。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/01/16 06:17