如果我有一个函数组合f(f(f(f(x))))
我怎么能把它写成C中的函数?是否可以用递归算法编写它?
例如,如果我们有以下功能会发生什么:
f(x)=cosa*X1+cosb*X2 where x=(X1,X2)
答案 0 :(得分:1)
这是我的一个示例玩具程序,一个将迭代与头部和头部进行比较的练习。尾递归。
对这个问题进行一点点破解,它重新应用了一个“wibble”函数N次,并通过struct array聚合X0,X1,通过reapply_f迭代和递归函数构建系列。重构尾调用优化版本,将代码变回看起来像迭代。 (只是使用typedef'd数组,有问题你无法从函数返回它,并且在传递给函数调用时没有按值语义调用。)
输出:
Iterative Series Technique
f0 = f(0.100000,0.900000)
f1 = f(1.000000,-0.800000)
f2 = f(0.200000,1.800000)
f3 = f(2.000000,-1.600000)
Head Recursive Series Technique
f0 = f(0.100000,0.900000)
f1 = f(1.000000,-0.800000)
f2 = f(0.200000,1.800000)
f3 = f(2.000000,-1.600000)
Tail Recursive Series Technique
f0 = f(0.100000,0.900000)
f1 = f(1.000000,-0.800000)
f2 = f(0.200000,1.800000)
f3 = f(2.000000,-1.600000)
Optimised Tail Recursive Series Technique
f0 = f(0.100000,0.900000)
f1 = f(1.000000,-0.800000)
f2 = f(0.200000,1.800000)
f3 = f(2.000000,-1.600000)
Tidied Optimised Tail Recursive Series Technique
f0 = f(0.100000,0.900000)
f1 = f(1.000000,-0.800000)
f2 = f(0.200000,1.800000)
f3 = f(2.000000,-1.600000)
和C,显示迭代和递归代码的相似性:
#include <stdio.h>
#include <stdlib.h>
typedef struct aggregate {
double X[2];
} aggregate;
void display_series(int n, aggregate series[]) {
for (int i=0; i<=n; i++) {
printf( " f%d = f(%f,%f)\n", i, series[i].X[0], series[i].X[1]);
}
putchar( '\n');
}
void init_series(int n, aggregate series[]) {
series[0].X[0] = 0.1; series[0].X[1] = 0.9;
for (int i=1; i <= n; i++) {
series[ i].X[0] = 0.0; series[ i].X[1] = 0.0;
}
}
aggregate wibble( const aggregate in) {
aggregate out;
out.X[0] = in.X[0] + in.X[1];
out.X[1] = in.X[0] - in.X[1];
return out;
}
aggregate reapply_f_iterative(int n, aggregate (*f)(), aggregate series[]) {
for (int i=1; i <= n; i++) {
series[ i] = (*f)( series[ i-1]);
}
return series[n];
}
aggregate reapply_f_head_recursive(int n, aggregate (*f)(), aggregate series[]) {
if (n>0) {
reapply_f_head_recursive( n-1, f, series);
series[n] = (*f)( series[n-1]);
}
return series[n];
}
aggregate reapply_f_tail_recursive( int applied, int limit, aggregate (*f)(), aggregate series[]) {
if (applied >= limit) {
return series[ applied];
}
series[applied+1] = (*f)( series[ applied]);
return reapply_f_tail_recursive( ++applied, limit, f, series);
}
aggregate reapply_f_optimised_tail_recursive( int applied, int limit, aggregate (*f)(), aggregate series[]) {
RESTART:
if (applied >= limit) {
return series[ applied];
}
series[applied+1] = (*f)( series[ applied]);
++applied;
goto RESTART;
}
aggregate reapply_f_tidied_optimised_tail_recursive( int applied, int limit, aggregate (*f)(), aggregate series[]) {
for( ; applied < limit; ++applied) {
series[ applied+1] = (*f)( series[ applied]);
};
return series[ applied];
}
int main (int argc, char **argv) {
/* series 0..N */
size_t N = 3;
if (argc == 2) {
N = strtol( argv[ 1], NULL, 0);
}
aggregate *series = calloc( N+1, sizeof( aggregate));
printf( "Iterative Series Technique\n");
init_series( N, series);
(void) reapply_f_iterative( N, &wibble, series);
display_series( N, series);
printf( "Head Recursive Series Technique\n");
init_series( N, series);
(void) reapply_f_head_recursive( N, &wibble, series);
display_series( N, series);
printf( "Tail Recursive Series Technique\n");
init_series( N, series);
(void) reapply_f_tail_recursive( 0, N, &wibble, series);
display_series( N, series);
printf( "Optimised Tail Recursive Series Technique\n");
init_series( N, series);
(void) reapply_f_optimised_tail_recursive( 0, N, &wibble, series);
display_series( N, series);
printf( "Tidied Optimised Tail Recursive Series Technique\n");
init_series( N, series);
(void) reapply_f_tidied_optimised_tail_recursive( 0, N, &wibble, series);
display_series( N, series);
}
答案 1 :(得分:0)
如果我正确理解了你的意思,你总是可以将计数器设置为你希望调用该函数的次数,并将其作为该函数的一个附加参数传递。然后每次调用函数一次将计数器减1,并在计数器为零时停止迭代。
答案 2 :(得分:0)
typedef struct composite {
float X1,
float X2
} composite;
composite f(composite x) {
composite result;
result.X1 = cosa*x.X1 + xosa*x.X2;
result.X2 = sina*x.X0 - cosa*x.X2;
return result;
}