Числовые рецепты вызова функции C Глава 10.3

#c #numerical-methods #numerical-computing

#c #численные методы #числовые вычисления

Вопрос:

У меня есть эта функция. Я немного новичок в C, и я не знаю, как вызвать эту функцию, чтобы получить результат:

 float dbrent(float ax, float bx, float cx, float (*f)(float),float (*df)(float), float tol, float* xmin)
{
    int iter, ok1, ok2;
    float a, b, d, d1, d2, du, dv, dw, dx, e = 0.0;
    float fu, fv, fw, fx, olde, tol1, tol2, u, u1, u2, v, w, x, xm;
    a = (ax < cx ? ax : cx);
    b = (ax > cx ? ax : cx);
    x = w = v = bx;
    fw = fv = fx = (*f)(x);
    dw = dv = dx = (*df)(x);

    for (iter = 1; iter <= ITMAX; iter  )
    {
        xm = 0.5 * (a   b);
        tol1 = tol * fabs(x)   ZEPS;
        tol2 = 2.0 * tol1;
        if (fabs(x - xm) <= (tol2 - 0.5 * (b - a))) {
            *xmin = x;
            return fx;
        }
        if (fabs(e) > tol1) {
            d1 = 2.0 * (b - a);
            d2 = d1;
            if (dw != dx) d1 = (w - x) * dx / (dx - dw);
            if (dv != dx) d2 = (v - x) * dx / (dx - dv);
            u1 = x   d1;
            u2 = x   d2;
            ok1 = (a - u1) * (u1 - b) > 0.0 amp;amp; dx * d1 <= 0.0;
            ok2 = (a - u2) * (u2 - b) > 0.0 amp;amp; dx * d2 <= 0.0;
            olde = e;
            e = d;
            if (ok1 || ok2) {
                if (ok1 amp;amp; ok2)
                    d = (fabs(d1) < fabs(d2) ? d1 : d2);
                else if (ok1)
                    d = d1;
                else
                    d = d2;
                if (fabs(d) <= fabs(0.5 * olde)) {
                    u = x   d;
                    if (u - a < tol2 || b - u < tol2)
                        d = SIGN(tol1, xm - x);
                }
                else {
                    d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
                }
            }
            else {
                d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
            }
        }
        else {
            d = 0.5 * (e = (dx >= 0.0 ? a - x : b - x));
        }
        if (fabs(d) >= tol1) {
            u = x   d;
            fu = (*f)(u);
        }
        else {
            u = x   SIGN(tol1, d);
            fu = (*f)(u);
            if (fu > fx) {
                *xmin = x;
                return fx;
            }
        }
        du = (*df)(u);
        if (fu <= fx) {
            if (u >= x) a = x; else b = x;
            MOV3(v, fv, dv, w, fw, dw)
                MOV3(w, fw, dw, x, fx, dx)
                MOV3(x, fx, dx, u, fu, du)
        }
        else {
            if (u < x) a = u; else b = u;
            if (fu <= fw || w == x) {
                MOV3(v, fv, dv, w, fw, dw)
                    MOV3(w, fw, dw, u, fu, du)
            }
            else if (fu < fv || v == x || v == w) {
                MOV3(v, fv, dv, u, fu, du)
            }
        }
    }
    cout<<"Too many iterations in routine dbrent";
    return 0.0;
}
 

Этот код взят из числовых рецептов глава 10.3. Мне нужно вызвать эту функцию и получить результат, но я не знаю, как ее вызвать, особенно когда есть синтаксис типа float (*)(float) .

Заранее спасибо.

Комментарии:

1. Этот синтаксис соответствует функциям. Просто вызовите этот код с двумя функциями в качестве параметров

2. Вы слышали об указателях на функции ?

Ответ №1:

Что ж, давайте предположим, что у вас есть следующие функции:

 float df_(float yourFloat) {
  ...
  return yourFloat;
}
 

и

 float f_(float yourFloat) {
  ...
  return yourFloat;
}
 

Затем вы могли бы вызвать свою функцию следующим образом:

 float t =  dbrent(ax, bx, cx, amp;f_, amp;df_, tol, amp;xmin);
 

Где amp;xmin передается адрес некоторой переменной с плавающей xmin запятой .

Итак, по сути, вы указываете адрес своих функций f_ df_ и переменной с плавающей xmin запятой.

Ответ №2:

Мы можем позвонить dbrent несколькими способами, ниже показан один из способов.

Прототип вашей функции

 float dbrent ( float ax, float bx, float cx, 
               float (*f)(float),
               float (*df)(float), 
               float tol, float* xmin
             )
 

что вам нужно, так это func_f (вы можете использовать любое имя для функции), которая принимает float значение в качестве аргумента и возвращает float значение, как показано ниже.

 float func_f(float num)
{
    /* code */
}
 

вам нужна еще одна функция того же типа, что и упомянутая выше

 float func_df(float num)
{
    /* code */
}
 

Ниже приведена настройка, которую необходимо выполнить перед вызовом dbrent

 some_funtion()
{
    // setup to call dbrent
    // guess you know you need some values in it.
    float ax, bx,  cx, tol, xmin;
    float (*f)(float);
    float (*df)(float);
    f = func_f;
    df = func_df;

     //one way of calling dbrent
    dbrent(ax, bx,  cx, f, df,tol, xmin);

    //you can even directly call using the function names instead of using pointers
    dbrent(ax, bx, cx, func_f, func_df, tol, xmin);
}
 

ПРИМЕЧАНИЕ: переменные не были инициализированы для простоты, убедитесь, что вы передаете допустимые переменные при вызове функции.

Комментарии:

1. Почему бы просто не dbrent(ax, bx, cx, func1, func_df, tol, xmin); отбросить float (*f)(float); float (*df)(float); все вместе?

2. да, @Jabberwocky, я редактировал то же самое, и именно поэтому я упомянул в начале несколько способов :), в любом случае спасибо

3. Тем не менее наличие этих указателей на промежуточные функции f и df совершенно бессмысленно. Это просто усложняет чтение кода.

4. Я просто сообщал ему о разных способах, соглашался с объявлением f и df на самом деле не нужен, но вреда не было.