2017-07-27 273 views
2

我有一個SAS無法正常工作的宏。如果宏變量的值大於某個固定值,我會觸發%goto語句。宏變量由以下示例代碼創建;SAS宏變量與科學計數法的邏輯比較

proc sql noprint; 
select num into :num 
from table; 
quit; 

當打開表格時,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(); 
+0

SAS宏變量只是文本。 SAS宏只會生成更多文本。 – david25272

回答

2

因爲%if &j > 5不執行「數學」的比較,但實際上是一個文本比較。普通舊%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;,就已經出現了工作 - 因爲它只是比較57這是真的。

更妙的是,%let J = 5E8;會更大 - 因爲E是比沒有更大 - 但如果你比較&j > 5A它仍然會工作,而&j > 5F這是行不通的。在那裏它比較E(該字母)到F(該字母)並且發現F更大。

+0

謝謝,喬。我認爲這是沿着這些線的東西,這就是爲什麼我選擇1E8而不是像7E8那樣的東西,就像你上面提到的那樣。感謝您使用%sysevalf()的提示。我沒有意識到在這樣的情況下會需要它。 – timmyb357

+2

另請注意''sysevalf()'會讓你使用日期文字。 '%if%sysevalf(&mydate>'01jan2017'd)...' – Tom