2012-08-01

SCIP in C++11 ― 1.3.3節 その1


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 件のコメント :

コメントを投稿