2017-05-16 4 views
0

Ich würde gerne wissen, ob es in C++ einen Weg gibt, um zu funktionieren und andere Funktion mit einigen seiner festen Parameter zu übergeben.Pass-Funktion f (x, y) als Parameter mit y fixed

hier ein exemple zu erklären:

#include<math.h> 
#include<iostream> 

double myfunc(double x) { return 5*x; } 

double gaussian(double x , double s , double v) { return exp((x-v)*(x-v)/(s*s)) ; } 

double Trapeze1D(const double x_min, const double x_max, double (*fonction)(double)) 
{ 
    double nb_pts = 100.0 ; 
    double integrale = 0.0 ; 
    double dx = (x_max - x_min)/(double) nb_pts ; 

    double x_k ; 

    while (k < nb_pts-1) 
    { 
     k++; 
     x_k = x_min + (double) k * dx ; 
     integrale += fonction(x_k) ; 
    }  

    integrale *= dx ; 
    return integrale ; 
} 

int main() 
{ 
    cout << Trapeze1D(0.0,1.0,myfunc) << endl ; // <-- works fine 
    cout << Trapeze1D(0.0,1.0, gaussian(double , 2,3)) << endl ; // <-- I would like something like that ... 

    // Also tried : 
    double tmp(double x) = gaussian(x, 2,3) ; // <-- does not work C++ does not allow definition of function inside function ... 
    cout << Trapeze1D(0.0,1.0, tmp) << endl ; 
} 

Mein Problem folgendes ist, werde ich (die Integrationsmethode wird viel anspruchsvoller im Ende) verschiedene Arten von Funktionen und viele von ihnen integrieren müssen ist abhängig von Parametern wie gaussian, Polynom, beta-Gesetze ...

ich auch Klasse wie folgt versucht haben, mit:

class gaussian 
{ 
    public: 
    double eval(double x) ; 
    void get(double s, double v) ; 
    private: 
    double s ; 
    double v ; 
} 

double gaussian::eval(double x){ return exp((x-v)*(x-v)/(s*s)) ; } 

int main() 
{ 
    gaussian G; 
    G.get(1.0,2.0) ; 
    cout << Trapeze1D(0.0,1.0,G.eval) << endl ; // <-- error 
} 

aber ich th Der folgende Fehler: Verweis auf nicht statische Elementfunktion muss aufgerufen werden

Jede Hilfe wäre sehr willkommen. vielen dank

+3

Klingt wie Sie brauchen 'std :: function' und 'std :: bind'. – NathanOliver

+0

@NathanOliver nein er tut nicht – Sopel

Antwort

1

Es gibt ein paar Möglichkeiten, wie Sie das tun können. Am einfachsten ist es, die Sie tatsächlich sehr nahe waren:

int main() 
{ 
    std::cout << Trapeze1D(0.0, 1.0, myfunc) << std::endl; 

    auto tmp = [](double x){ return gaussian(x, 2, 3); }; 
    std::cout << Trapeze1D(0.0, 1.0, tmp) << std::endl; 
} 

Dies erzeugt eine temporäre Lambda-Funktion, die Ihre Gaußsche Funktion wickelt. Wenn Sie nicht vertraut mit Lambda-Ausdrücke sind, ist dies eine temporäre Version deklarieren tmp am Anfang der Datei:

double myfunc(double x) { return 5*x; } 

double gaussian(double x , double s , double v) { return exp((x-v)*(x-v)/(s*s)) ; } 

double tmp(double x) { return gaussian(2, 3, x); } 

Wenn Sie wollten diese flexibler sein, und Sie waren interessiert wechselnden s und v etwas regelmäßig konnte man immer eine Funktor Klasse machen, aber das zu einem bisschen Arbeit, wenn Sie Ihre Trapeze1D Funktion nehmen Sie entweder in einem Funktionszeiger oder ein Funktor bedeuten würde:

template <typename FuncType> 
double Trapeze1D(const double x_min, const double x_max, FuncType fonction) 
{ 
    ... 
    integrale += fonction(x_k); 
    ... 
} 

class gaussian_functor 
{ 
public: 
    gaussian_functor(double s, double v) 
     : m_s(s) 
     , m_v(v) 
    {} 

    double operator() (double x) const { return exp((x - m_v)*(x - m_v)/(m_s*m_s)); } 
private: 
    double m_s; 
    double m_v; 
}; 


int main() 
{ 
    std::cout << Trapeze1D(0.0, 1.0, myfunc) << std::endl; 

    gaussian_functor my_functor(2.0, 3.0); 
    std::cout << Trapeze1D(0.0, 1.0, my_functor) << std::endl; 
} 
+0

Können Sie erklären, warum in der Definition der Funktion Trapeze1D geändert werden muss von: double (* fonction) (double) zu FuncType fonction? – Bastien

+0

Kennen Sie Vorlagen? Wenn ich die Definition so ändere, dass sie wie oben beschrieben templatiert wird, kann jedes Objekt als "Funktion" aufgenommen werden, solange das Objekt eine Funktion hat, die aufgerufen wird, indem es ein "double" übergeben wird und ein "double" zurückgibt. Mit der Templates-Definition können Sie den Funktionszeiger wie zuvor übergeben und auch einen Funktor übergeben. – dwcanillas

+0

Vielen Dank an alle, die mein Problem gelöst haben! – Bastien

Verwandte Themen