2013-03-18 2 views
2

나는 초기 추측 init, 단항 기능 f 및 인수로 허용 tol를 취하는 뉴턴 랩슨 루트 찾기 알고리즘의 간단한 구현을 썼다 :C++는 아래 그림과 같이 뉴턴 랩슨 및 과부하 기능

bool newton_raphson(double& init, 
        double(*f)(double), 
        double tol){ 
    const int max_iter = 10000; 
    double next_x, soln = init; 
    int i = 0; 

    while(++i < max_iter){ 
     next_x = soln - f(soln)/fp_x(f, soln); 
     if(fabs(next_x - soln) < tol){ 
      init = next_x; 
      return true; 
     } 
     soln = next_x; 
    } 
    return false; 
} 

double fp_x(double(*f)(double), 
      double x){ 
    const double h = 0.000001; 
    return (f(x + h) - f(x - h))/2.0/h; 
} 

내 질문은 :이 완전히 완벽하게 단항 함수에 대한 작동하지만 함수가 하나 이상의 매개 변수가있는 f 있지만 하나의 매개 변수를 제외한 모든 상수 값을 가지고 작동하도록 구현을 변경하고 싶습니다. 명확히하기 위해서 : 아래에 보이는 함수 f (x) = 3x + 2가있는 경우

double f(double x){ 
    return (3*x + 2); 
} 

그런 다음 구현이 작동합니다. 그러나, 나는 주어진 수의 인수를 가진 모든 함수에서 작동하지만 첫 번째 인수 만이 가변적이다. I는 함수 f (x, y) = 3X + 2Y

double f(double x, double y){ 
    return (3*x + 2*y); 
} 

I는 F의 루트 발견하고자하는 (X, 2), 또는 F 그래서, 만약의 (X, 3)와 동일한 기능을 이용하여 , 그리고 하나 또는 두 개의 인수가 아닌 n 개의 인수에 대해서도 마찬가지입니다 (예제에서 보여준 함수가 단순 선형 함수라는 생각을 무시하십시오, 이것은 단지 예일뿐입니다). 다양한 인수에 대해 함수를 구현할 방법이 있습니까? 아니면 모든 경우에 구현을 작성해야합니까?

감사합니다,

NAX

참고

당신은 지금 말할 수있는,이 질문은 정말 뉴턴 - 랩슨에 대해 아니지만, 내가로 사용하는 경우는 그것을 쉽게 실제 질문에 대한 예로서, 다른 수의 인수를 가진 함수에 대한 단일 구현입니다. 사용 std::bindstd::function 아래

UPDATE

몇 가지 답변은 실제로 더 나은 선택한 답변보다 내 질문을 해결하는 문제를 해결하기 위해; 그러나, 그들은 C++ 11 라이브러리 클래스/함수입니다. (저를 잘못 이해하지 말고, 모든 C++ 프로그래머에게 먼저 배우고 배울 것을 강력히 권합니다.) 그리고이 글을 쓰는 시점에서 저는 몇 가지 문제에 직면했습니다. 그들을 사용하여; Eclipse Juno는 g ++ 4.7 (C++ 11 호환)을 사용하여 여전히 std::function을 인식하지 못했기 때문에 아래 체크 된 대답을 고수하기로 결정했습니다.

+0

처럼 호출 할 수 있습니다'n'은 당신이 컨테이너를 통해 모든 뿌리를 반환해야한다는 공평하지? 또는 당신이 원하는 그 것이다 예를 들어, 각 호출에서 세 번째 루트를 계산하려면? –

+0

나는 당신이 대답을 너무 빨리 받아 들였다고 생각한다. –

답변

2

난 당신이 가변 기능을 요구 있다고 생각 : 위의 인용

A variadic function – a function declared with a parameter list ending with ellipsis (...) – can accept a varying number of arguments of differing types. Variadic functions are flexible, but they are also hazardous. The compiler can't verify that a given call to a variadic function passes an appropriate number of arguments or that those arguments have appropriate types. Consequently, a runtime call to a variadic function that passes inappropriate arguments yields undefined behavior. Such undefined behavior could be exploited to run arbitrary code. From here:

https://www.securecoding.cert.org/confluence/display/cplusplus/DCL31-CPP.+Do+not+define+variadic+functions

그러나, 그들과 함께 문제가 있습니다.

가장 주목할만한 점은 컴파일 시간이 인 것입니다.당신이 하나를 구현에 관심이 있다면

그러나, 여기에 좋은 예와 기사는 다음과 같습니다

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=138

UPDATE : IMO

, 난 당신이 기능을 정의하는 것이 더 낫다 생각 구조체 또는 객체 인수 (즉, 일반 함수 객체)를 가져 와서 해당 인수에서 작동하는 함수를 작성하십시오 .

다른 옵션은 컴파일 시간을 reflection으로하는 것입니다.이 방법이 유용 할 수 있지만 이와 같은 예에서는 너무 많은 문제가 있습니다. 게다가 C++의 "reflection"은 "true"reflection이 아니라 다소 불량하고 불완전한 구현입니다.

2

당신이 여기서하려고하는 것은 std::bind입니다 (또는 C++ 03 컴파일러를 사용하는 경우 std::bind1ststd::bnd2nd).

이러한 매개 변수를 사용하면 다른 매개 변수에 값을 "바인딩"할 수 있으므로 단일 매개 변수 만 필요로하는 함수 (기술적으로는 함수 개체)가 남습니다.

당신이 이상적으로 같은이 같은 것 것 것 :

double f(double x, double y) { 
    return 3*x + 2*y; 
} 

double init = 1.0; 

newton_raphson(init, std::bind2nd(f, 3), 1e-4); 

불행하게도, 실제 사용, 그것은 아주 간단 아니에요 - std::bind2nd 작동하도록, 당신은 실제 기능을 사용할 수 없습니다; 대신 함수 객체를 사용해야하고 std::binary_function에서 파생되어야합니다.

std::bind은 유연성이 뛰어나므로 거의 모든 경우 가능합니다.

0

std::bindstd::function을 사용할 수 있습니다. 유형 std::function<double(double)>은 double을 취해 double을 반환하는 기능을 나타냅니다. 비슷하게 std::function<double(int,int)>은 2 int를 취하는 함수이며 double을 반환합니다.

#include <functional> 

bool newton_raphson(double& init, 
        std::function<double(double)>& f, 
        double tol){ 
    const int max_iter = 10000; 
    double next_x, soln = init; 
    int i = 0; 

    while(++i < max_iter){ 
     next_x = soln - f(soln)/fp_x(f, soln); 
     if(fabs(next_x - soln) < tol){ 
      init = next_x; 
      return true; 
     } 
     soln = next_x; 
    } 
    return false; 
} 

double myfunction(double x, double y){ 
    return (3*x + 2*y); 
} 
double fp_x(std::function<double(double)> f, double x) { 
    ... 
} 
... 
double d = 1.0; 
// Here we set y=2.5 and we tell bind that 1st parameter is unbounded 
// If we wanted to switch and set x=2.5 and let y be unbounded, then 
// we would use (&myfunction, 2.5, std::placeholders::_1) 
newton_raphson(d, std::bind(&myfunction, std::placeholders::_1, 2.5) , 1e-6); 
... 
+0

이 답변을 주셔서 감사합니다. 사실 직접 질문을 다루는 것으로 보이기 때문에이 방법을 선호합니다. 그러나 두 가지 질문이 있습니다. 첫째, 템플릿 함수형 변수에 식별자가 있어야합니다 (예 : fp_x 안의 선언)? 그리고 그렇지 않다면 구문은 어떻게 될까요? 또한 g ++을 사용하여이 작업을 시도하고'function '을 사용하면'Symbol'함수 '를 해결할 수 없습니다.'오류가 발생합니다. 왜 그런지 알아? – naxchange

+0

나는 또한'-std = C++ 11'을 사용하여 우분투 12.10에서 g ++ 4.7을 사용하여 이것을 시도했지만 여전히 해결되지 않았습니다. 이클립스 주노를 사용하고 있습니다 – naxchange

+0

@naxchange, 불행히도 이것은 C++ 11입니다. 을 포함했다고 가정합니다. –

0

내가 C++ 11 가변 템플릿을 배우도록 강요하는 방법으로 질문을 사용했습니다. 여기서는 작동 예제입니다. 당신이 개까지 뿌리를 발견하면

template< typename... Ts > 
double f(Ts... Vs) { 
    double array[] = { Vs... }; 
    int numArg = sizeof...(Vs); 
    switch (numArg) { 
    case 1: 
     return 3 * array[0] + 2; 
    case 2: 
     return 3 * array[0] + 2 * array[1]; 
    case 3: 
     return 3 * array[0] + 2 * array[1] + 1 * array[3]; 
    .... 
    default: 
     return 0.0; 
    } 
} 

template< typename... Ts > 
double newton_raphson(double &init, double tol, 
         double (*func) (Ts... Vs), Ts... Vs) { 
    return func(Vs...); 
} 

당신이

newton_raphson(&init, 1.0, f, 1.0, 2.0, 3.0, 4.0, 5.0); 
관련 문제