#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
на самом деле не нужен, но вреда не было.