SAS 宏变量逻辑比较与科学记数法
SAS Macro Variable Logical Comparison with Scientific Notation
我在 SAS 中有一个宏无法正常工作。我有一个 %goto 语句,如果宏变量的值大于某个固定数字,就会触发该语句。宏变量由以下示例代码创建;
proc sql noprint;
select num into :num
from table;
quit;
当打开table时,num变量有标准符号的数字(例如645,435,243)。但是,宏变量&num。把它选为 6.4544E8。当 SAS 尝试将此值与 1,000,000 等数字进行比较时,这会导致出现问题。
我能够用下面的简单宏重现这个问题,唯一的区别在于宏变量赋值的方式。在下面的代码中,我直接分配 j 1E8 而不是通过 proc sql 语句。
我的问题是:为什么 SAS 无法正确计算 1E8 > 5?
%macro test();
%let i = 1;
%let j = 1E8;
data test0;
x = &i.;
output;
run;
%let i = 2;
%do %until (&i. = 11);
%put &i.;
%if &i. >= 7 %then %do;
%if &j. > 5 %then %do;
%goto done;
%end;
%end;
data test&i.;
x = &i.;
output;
run;
proc append base=test0 data=test&i.;
run;
proc datasets library=work nolist;
delete test&i.;
run;
%let i = %eval(&i + 1);
%end;
%done: %mend;
%test();
因为 %if &j > 5
不是在执行 "mathematical" 比较,而是有效的文本比较。常规的旧 %eval
只会进行整数数学运算,比较基本上只是将两者作为文本进行比较。 SAS 宏变量几乎总是被视为文本,而不是其他任何东西,因此如果您希望 SAS 首先将它们视为数字,请始终使用 %sysevalf
- 或者使用常规数据步变量。
如果你想让SAS把宏变量内容当作实数,你需要使用%sysevalf
。
%if &i. >= 7 %then %do;
%if %sysevalf(&j. > 5,boolean) %then %do;
%goto done;
%end;
%end;
请注意,如果您选择了 %let j = 7E8;
,它似乎会起作用 - 因为它只是将 5
与 7
进行比较,这是事实。
甚至更好,%let J = 5E8;
会更大——因为 E 总比没有大——但是如果你比较 &j > 5A
它仍然有效,而 &j > 5F
则无效。它在那里比较 E
(字母)和 F
(字母),发现 F 更大。
我在 SAS 中有一个宏无法正常工作。我有一个 %goto 语句,如果宏变量的值大于某个固定数字,就会触发该语句。宏变量由以下示例代码创建;
proc sql noprint;
select num into :num
from table;
quit;
当打开table时,num变量有标准符号的数字(例如645,435,243)。但是,宏变量&num。把它选为 6.4544E8。当 SAS 尝试将此值与 1,000,000 等数字进行比较时,这会导致出现问题。
我能够用下面的简单宏重现这个问题,唯一的区别在于宏变量赋值的方式。在下面的代码中,我直接分配 j 1E8 而不是通过 proc sql 语句。
我的问题是:为什么 SAS 无法正确计算 1E8 > 5?
%macro test();
%let i = 1;
%let j = 1E8;
data test0;
x = &i.;
output;
run;
%let i = 2;
%do %until (&i. = 11);
%put &i.;
%if &i. >= 7 %then %do;
%if &j. > 5 %then %do;
%goto done;
%end;
%end;
data test&i.;
x = &i.;
output;
run;
proc append base=test0 data=test&i.;
run;
proc datasets library=work nolist;
delete test&i.;
run;
%let i = %eval(&i + 1);
%end;
%done: %mend;
%test();
因为 %if &j > 5
不是在执行 "mathematical" 比较,而是有效的文本比较。常规的旧 %eval
只会进行整数数学运算,比较基本上只是将两者作为文本进行比较。 SAS 宏变量几乎总是被视为文本,而不是其他任何东西,因此如果您希望 SAS 首先将它们视为数字,请始终使用 %sysevalf
- 或者使用常规数据步变量。
如果你想让SAS把宏变量内容当作实数,你需要使用%sysevalf
。
%if &i. >= 7 %then %do;
%if %sysevalf(&j. > 5,boolean) %then %do;
%goto done;
%end;
%end;
请注意,如果您选择了 %let j = 7E8;
,它似乎会起作用 - 因为它只是将 5
与 7
进行比较,这是事实。
甚至更好,%let J = 5E8;
会更大——因为 E 总比没有大——但是如果你比较 &j > 5A
它仍然有效,而 &j > 5F
则无效。它在那里比较 E
(字母)和 F
(字母),发现 F 更大。