在 SAS 中实现递归二分法
Implementing recursive bisection in SAS
这里是第一个问题。
基本上,我想通过使用宏在 SAS 中实现递归二分算法。我已经编写了一个宏,它接受两个参数(当前区间的下端点和上端点)并生成一个 table 包含另一个区间的两个端点。我遇到的问题是编写一个宏来迭代这个过程,直到间隔的宽度低于某个阈值。
这是我目前所知道的,但是代码没有像我预期的那样工作。请记住,我所学的 SAS 知识的 99% 都是在过去三天左右学到的。非常感谢任何可以提供帮助的人!
data interval;
input a b;
datalines;
0 1
;
run;
%macro iter(a,b);
data rec;
set interval;
%let a0 = &a;
%let b0 = &b;
%do %while(%sysevalf(&b0 - &a0) > .00001);
%nextint(&a0,&b0);
call symput('a0',trim(left(a)));
call symput('b0',trim(left(b)));
%end;
run;
%mend;
其中 %nextint(&a0,&b0)
产生一个 table interval
和一个观察值,两列 a
和 b
的值从 &a0
和 &b0
。如您所见,SAS 对我来说完全是个谜,我不知道自己在做什么。
我建议您查看 SAS/IML 语法来进行数值分析工作。
Rick Wicklin 的 This blog 解释了如何使用 SAS/IML 求函数的根。
如果您仍想使用宏和数据步骤,可以使用
options mprint;
语句来调试您的代码并在日志中查看哪些命令实际上是 运行.
不确定你的宏 %nextint 是做什么的,但我写了一些东西只是为了展示 %iter 宏将如何运行。
您需要将这些调用 symput 放在数据步骤中。
我在这里使用null只是为了从区间数据集中获取宏变量a0和b0的新值。
注意,这将生成具有第一组 a 和 b 值的区间数据集,其中 b - a 小于 0.0001。
宏末尾的 %put 语句将显示每次交互时 a 和 b 的变化值。
%macro nextint(a1,b1);
data interval;
a = &a1. + 0.1;
b = &b1. - 0.1;
run;
%mend;
%macro iter(a,b);
%let a0 = &a.;
%let b0 = &b.;
%do %while(%sysevalf(%sysevalf(&b0. - &a0.) > 0.0001));
%nextint(&a0,&b0);
data _null_;
set interval;
call symput('a0',strip(a));
call symput('b0',strip(b));
run;
%put &a0.;
%put &b0.;
%put %sysevalf(&b0. - &a0.);
%end;
%mend;
%iter(0,1);
这里是第一个问题。
基本上,我想通过使用宏在 SAS 中实现递归二分算法。我已经编写了一个宏,它接受两个参数(当前区间的下端点和上端点)并生成一个 table 包含另一个区间的两个端点。我遇到的问题是编写一个宏来迭代这个过程,直到间隔的宽度低于某个阈值。
这是我目前所知道的,但是代码没有像我预期的那样工作。请记住,我所学的 SAS 知识的 99% 都是在过去三天左右学到的。非常感谢任何可以提供帮助的人!
data interval;
input a b;
datalines;
0 1
;
run;
%macro iter(a,b);
data rec;
set interval;
%let a0 = &a;
%let b0 = &b;
%do %while(%sysevalf(&b0 - &a0) > .00001);
%nextint(&a0,&b0);
call symput('a0',trim(left(a)));
call symput('b0',trim(left(b)));
%end;
run;
%mend;
其中 %nextint(&a0,&b0)
产生一个 table interval
和一个观察值,两列 a
和 b
的值从 &a0
和 &b0
。如您所见,SAS 对我来说完全是个谜,我不知道自己在做什么。
我建议您查看 SAS/IML 语法来进行数值分析工作。
Rick Wicklin 的This blog 解释了如何使用 SAS/IML 求函数的根。
如果您仍想使用宏和数据步骤,可以使用
options mprint;
语句来调试您的代码并在日志中查看哪些命令实际上是 运行.
不确定你的宏 %nextint 是做什么的,但我写了一些东西只是为了展示 %iter 宏将如何运行。
您需要将这些调用 symput 放在数据步骤中。
我在这里使用null只是为了从区间数据集中获取宏变量a0和b0的新值。
注意,这将生成具有第一组 a 和 b 值的区间数据集,其中 b - a 小于 0.0001。
宏末尾的 %put 语句将显示每次交互时 a 和 b 的变化值。
%macro nextint(a1,b1);
data interval;
a = &a1. + 0.1;
b = &b1. - 0.1;
run;
%mend;
%macro iter(a,b);
%let a0 = &a.;
%let b0 = &b.;
%do %while(%sysevalf(%sysevalf(&b0. - &a0.) > 0.0001));
%nextint(&a0,&b0);
data _null_;
set interval;
call symput('a0',strip(a));
call symput('b0',strip(b));
run;
%put &a0.;
%put &b0.;
%put %sysevalf(&b0. - &a0.);
%end;
%mend;
%iter(0,1);