1.3.3節 一般的方法としての手続き
もともとC++では関数は、たとえファンクタやラムダを使おうと、
そのままでは第1級オブジェクトではないわけなので
(変態的にテンプレート使ったらできるんだろうけれど)、
なにがなんでも第1級オブジェクトとして扱って混乱するより、
その都度問題が解ける程度にラムダやテンプレート関数を使い分けることにした方がいいな。
その方が実用で使うセンスが身につくだろうし。
区間二分法
------
const
function<double(double,double)> average=
[](const double a,const double
b){return((a+b)/2.0);};
const
function<bool(double,double)> isCloseEnough=
[](const double x,const double
y){return(abs(x-y)<0.001);};
const
double search
(const
function<double(double)>& f,
const double negativePoint,
const double positivePoint)
{
const double
midPoint(average(negativePoint,positivePoint));
if(isCloseEnough(negativePoint,positivePoint)){
return(midPoint);
}else{
const double testValue(f(midPoint));
if(testValue>0){return(search(f,negativePoint,midPoint));}
else
if(testValue<0){return(search(f,midPoint,positivePoint));}
else{return(midPoint);}
}
}
const
double halfIntervalMethod
(const
function<double(double)>& f,
const double a, const double b)
{
const double aValue(f(a));
const double bValue(f(b));
if(aValue<0 &&
bValue>0){return(search(f,a,b));}
else if (bValue<0 &&
aValue>0){return(search(f,b,a));}
else{
cerr<<"Values are not of
opposite sign "<<a<<" "<<b<<endl;
exit(1);
}
}
int
main(int argc, char** argv)
{
cout<<setprecision(16)
<<"zero of sin(x): x="
<<halfIntervalMethod([](const
double x)
{return(sin(x));},2.0,4.0)<<endl;
cout<<setprecision(16)
<<"zero of x^3-2x-3: x="
<<halfIntervalMethod
([](const double
x){return(pow(x,3)-2.0*x-3.0);},
1.0,2.0)<<endl;
return(0);
}
-----
出力
-----
zero
of sin(x): x=3.14111328125
zero
of x^3-2x-3: x=1.89306640625
0 件のコメント :
コメントを投稿