嵌套函数指针或函数组合
Nested function pointers or function composition
我正在研究微积分运算(例如导数、积分等...)的 C 实现。例如,这是我的 derivative
函数的模板定义:
double derivative(double (*f)(double), double x);
假设我想计算 exp
在 1 处的导数,那么调用将是:derivative(exp, 1);
非常基本的东西。现在我的问题是,我将如何着手(如果可能的话)将合成传递给我的 derivative
函数?我尝试通过 exp(cos)
得到了我
error: passing 'double (double)' to parameter of incompatible type 'double'
.
我该怎么做?有可能吗?
我想你是在问这个:
double composition(double x) {
return exp(cos(x));
}
derivative(composition, 1);
许多语言允许您执行如下操作,但 C 没有匿名函数:
derivative(x => exp(cos(x)), 1);
C没有任何函数组合操作。要计算 exp∘cos 的导数,您可以定义函数 expcos
:
double expcos(double x)
{
return exp(cos(x));
}
并对其求导。
对于更通用的解决方案,您可以修改派生例程以同时采用函数指针和 const void *
转发给函数。该函数会将 const void *
作为参数,将其转换为指向该函数特定类型的 const
结构的指针,并从该结构中获取数据。然后函数组合可以用 compose
函数实现,该函数使用包含两个函数指针的结构。但是,这意味着您需要为 exp
和 cos
等接受但忽略 const void *
.
的普通函数使用代理例程
如果你想对合成进行某种 运行 时间控制,你可以编写一个函数,将函数指针数组计算为一个合成:
// calls functions in reverse order
double compose(size_t n, double (* const fc[])(double), double x)
{
while (n--)
{
x = fc[n](x);
}
return x;
}
这可以从您的派生函数的另一个版本调用:
double derivative_composed(size_t n, double (* const fc[])(double), double x)
{
// Example implementation for illustrative purpose only.
double fx, fxh, h;
h = x / 1e10;
if (h == 0)
{
h = 1e-10;
}
fx = compose(n, fc, x);
fxh = compose(n, fc, x + h);
return (fxh - fx) / h;
}
为避免重复代码,可以将您原来的 derivative
函数更改为使用单个函数调用 derivative_composed
的包装器:
double derivative(double (* const f), double x)
{
return derivative_composed(1, &f, x);
}
用法示例:
int main(void)
{
double (* const fc[2])(double) = { exp, cos };
double x = 1.0;
double xprime = derivative_composed(2, fc, x);
printf("x = %f, xprime = %f\n", x, xprime);
}
输出:
x = 1.000000, xprime = -1.444407
我正在研究微积分运算(例如导数、积分等...)的 C 实现。例如,这是我的 derivative
函数的模板定义:
double derivative(double (*f)(double), double x);
假设我想计算 exp
在 1 处的导数,那么调用将是:derivative(exp, 1);
非常基本的东西。现在我的问题是,我将如何着手(如果可能的话)将合成传递给我的 derivative
函数?我尝试通过 exp(cos)
得到了我
error: passing 'double (double)' to parameter of incompatible type 'double'
.
我该怎么做?有可能吗?
我想你是在问这个:
double composition(double x) {
return exp(cos(x));
}
derivative(composition, 1);
许多语言允许您执行如下操作,但 C 没有匿名函数:
derivative(x => exp(cos(x)), 1);
C没有任何函数组合操作。要计算 exp∘cos 的导数,您可以定义函数 expcos
:
double expcos(double x)
{
return exp(cos(x));
}
并对其求导。
对于更通用的解决方案,您可以修改派生例程以同时采用函数指针和 const void *
转发给函数。该函数会将 const void *
作为参数,将其转换为指向该函数特定类型的 const
结构的指针,并从该结构中获取数据。然后函数组合可以用 compose
函数实现,该函数使用包含两个函数指针的结构。但是,这意味着您需要为 exp
和 cos
等接受但忽略 const void *
.
如果你想对合成进行某种 运行 时间控制,你可以编写一个函数,将函数指针数组计算为一个合成:
// calls functions in reverse order
double compose(size_t n, double (* const fc[])(double), double x)
{
while (n--)
{
x = fc[n](x);
}
return x;
}
这可以从您的派生函数的另一个版本调用:
double derivative_composed(size_t n, double (* const fc[])(double), double x)
{
// Example implementation for illustrative purpose only.
double fx, fxh, h;
h = x / 1e10;
if (h == 0)
{
h = 1e-10;
}
fx = compose(n, fc, x);
fxh = compose(n, fc, x + h);
return (fxh - fx) / h;
}
为避免重复代码,可以将您原来的 derivative
函数更改为使用单个函数调用 derivative_composed
的包装器:
double derivative(double (* const f), double x)
{
return derivative_composed(1, &f, x);
}
用法示例:
int main(void)
{
double (* const fc[2])(double) = { exp, cos };
double x = 1.0;
double xprime = derivative_composed(2, fc, x);
printf("x = %f, xprime = %f\n", x, xprime);
}
输出:
x = 1.000000, xprime = -1.444407