在SAS数据步骤中写入Ackermann函数
为了理解SAS中的递归编程,我曾多次尝试编写一个双参数Ackermann函数的版本,但都没有成功在SAS数据步骤中写入Ackermann函数,sas,computation-theory,Sas,Computation Theory,为了理解SAS中的递归编程,我曾多次尝试编写一个双参数Ackermann函数的版本,但都没有成功 data testa; do i=0 to 3; do j=0 to 3; a=input(resolve(cats('%a(',i,',',j,')')),32.); output; end;end; run; proc print; run; 该函数声明: 我只打算计算0-3范围内的值的m&n,因为m>=4的值会导致返回值迅速变大 我拍摄的是一个相对简单的输出;比如:
data testa;
do i=0 to 3; do j=0 to 3;
a=input(resolve(cats('%a(',i,',',j,')')),32.);
output;
end;end;
run;
proc print; run;
该函数声明:
我只打算计算0-3范围内的值的m&n,因为m>=4的值会导致返回值迅速变大
我拍摄的是一个相对简单的输出;比如:
Ack(0,0) = 1
Ack(0,1) = 2
Ack(0,2) = 3
Ack(0,3) = 4
Ack(1,0) = 2
Ack(1,1) = 3
依此类推至Ack3,3=61
我无法在网上找到在SAS中执行此操作的人的任何参考资料。所以,如果有人能帮我,我会非常感激
谢谢 在普通SAS代码中进行递归是困难的。但在宏代码中很容易实现
%macro a(m,n);
%if %sysfunc(verify(&m.&n,0123456789)) %then %do;
%put WARNING: Invalid input to macro &sysmacroname.. Use only non-negative integers.;
.
%end;
%else %if (&m=0) %then %eval(&n+1);
%else %if (&n=0) %then %a(%eval(&m-1),1);
%else %a(%eval(&m-1),%a(&m,%eval(&n-1)));
%mend a;
如果必须使用DataSet变量的值,则可以考虑使用Selp函数。
data testa;
do i=0 to 3; do j=0 to 3;
a=input(resolve(cats('%a(',i,',',j,')')),32.);
output;
end;end;
run;
proc print; run;
结果
Obs i j a
1 0 0 1
2 0 1 2
3 0 2 3
4 0 3 4
5 1 0 2
6 1 1 3
7 1 2 4
8 1 3 5
9 2 0 3
10 2 1 5
11 2 2 7
12 2 3 9
13 3 0 5
14 3 1 13
15 3 2 29
16 3 3 61
当然,如果您只打算使用从0到3的参数,那么您可能只需要使用数组查找
data testb;
array _a(0:3,0:3) _temporary_
(1 2 3 4
2 3 4 5
3 5 7 9
5 13 29 61
);
do i=0 to 3; do j=0 to 3; a=_a(i,j); output; end; end;
run;
在普通SAS代码中很难进行递归。但在宏代码中很容易实现
%macro a(m,n);
%if %sysfunc(verify(&m.&n,0123456789)) %then %do;
%put WARNING: Invalid input to macro &sysmacroname.. Use only non-negative integers.;
.
%end;
%else %if (&m=0) %then %eval(&n+1);
%else %if (&n=0) %then %a(%eval(&m-1),1);
%else %a(%eval(&m-1),%a(&m,%eval(&n-1)));
%mend a;
如果必须使用DataSet变量的值,则可以考虑使用Selp函数。
data testa;
do i=0 to 3; do j=0 to 3;
a=input(resolve(cats('%a(',i,',',j,')')),32.);
output;
end;end;
run;
proc print; run;
结果
Obs i j a
1 0 0 1
2 0 1 2
3 0 2 3
4 0 3 4
5 1 0 2
6 1 1 3
7 1 2 4
8 1 3 5
9 2 0 3
10 2 1 5
11 2 2 7
12 2 3 9
13 3 0 5
14 3 1 13
15 3 2 29
16 3 3 61
当然,如果您只打算使用从0到3的参数,那么您可能只需要使用数组查找
data testb;
array _a(0:3,0:3) _temporary_
(1 2 3 4
2 3 4 5
3 5 7 9
5 13 29 61
);
do i=0 to 3; do j=0 to 3; a=_a(i,j); output; end; end;
run;
下面是一个SAS/AF类实现 sasuser.examples.ackermanclass.scl sasuser.examples.ackermantest.scl 使用AFA C=sasuser.examples.ackermantest.scl进行测试
下面是一个SAS/AF类实现 sasuser.examples.ackermanclass.scl sasuser.examples.ackermantest.scl 使用AFA C=sasuser.examples.ackermantest.scl进行测试
下面是使用递归的Proc DS2示例:
proc ds2;
data _null_;
method ackerman(int m, int n) returns int;
if m=0 then return n+1;
if m > 0 then do;
if n = 0 then return ackerman ( m-1, 1 );
if n > 0 then return ackerman ( m-1, ackerman ( m, n-1 ) );
return -1;
end;
return -1;
end;
method init();
declare int m n result;
do m = 0 to 3;
do n = 0 to 3;
result = ackerman(m,n);
put m= n= result=;
end;
end;
end;
enddata;
run;
quit;
下面是使用递归的Proc DS2示例:
proc ds2;
data _null_;
method ackerman(int m, int n) returns int;
if m=0 then return n+1;
if m > 0 then do;
if n = 0 then return ackerman ( m-1, 1 );
if n > 0 then return ackerman ( m-1, ackerman ( m, n-1 ) );
return -1;
end;
return -1;
end;
method init();
declare int m n result;
do m = 0 to 3;
do n = 0 to 3;
result = ackerman(m,n);
put m= n= result=;
end;
end;
end;
enddata;
run;
quit;
过程fcmp实施:
/* Define */
proc fcmp outlib=work.funcs.math;
function ackerman(m, n);
if m = 0 then return(n + 1);
else if n = 0 then return(ackerman(m - 1, 1));
else return(ackerman(m - 1, ackerman(m, n - 1)));
endsub;
run;
quit;
/*Test*/
option cmplib = work.funcs;
proc fcmp;
out = ackerman(3,2);
put "Testing Function Call";
put "ackerman(3,2) returns:" out;
quit;
过程fcmp实施:
/* Define */
proc fcmp outlib=work.funcs.math;
function ackerman(m, n);
if m = 0 then return(n + 1);
else if n = 0 then return(ackerman(m - 1, 1));
else return(ackerman(m - 1, ackerman(m, n - 1)));
endsub;
run;
quit;
/*Test*/
option cmplib = work.funcs;
proc fcmp;
out = ackerman(3,2);
put "Testing Function Call";
put "ackerman(3,2) returns:" out;
quit;
请共享您迄今为止尝试过的代码,也许有人可以帮助您使其工作。请共享您迄今为止尝试过的代码,也许有人可以帮助您使其工作。出于某种原因,mine开始返回从1,1观测obs 6开始的缺失值。确保使用%EVAL传递减去的值,而不仅仅是文本1-1。我同意。我希望自己能看到一个PROC FCMP解决方案。出于某种原因,我的解决方案开始返回从1,1观察obs 6开始的缺失值。确保使用%EVAL传递减去的值,而不仅仅是文本1-1。我同意。我希望自己能看到一个PROC FCMP解决方案。