BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
ashlicole
Obsidian | Level 7

Hi everyone,

I'm perplexed by a situation I've encountered and I'm wondering if anyone can explain to me the inner SAS workings behind this.

I have a list of macros variables that I am scrolling through and subjecting to macro conditional logic. Something like this:

%let var1=0.1;

%let var2=0.5;

%let var3=1.5;

%let var4= ;

%let var5=0;

%macro q;

%if  0 < &&var&i < 1 %then %put &&var&i is between 0 and 1;

%else %put &&var&i is not between 0 and 1;

%mend q;

%q

My issue is this: the macro variable that is null (in this case, &var4) seems to resolve this condition as TRUE! This seems strange to me! I understand that a null value of a macro variable is not the same as a missing value of a data step variable, but I'm still not sure why this should resolve as being 0<var<1. I have tried other conditions, such as %IF &&VAR&I > 1 and these do NOT resolve as TRUE.

I have managed to get this code running fine using solutions to check for macro variables with null values prior to my conditional logic step, but my questions is WHY does &var4 resolve as being between 0 and 1? Can anyone explain to me the SAS workings behind this? Like I said, the code is working find with some work-arounds, but I am curious to know the reason behind it.

Thanks in advance for any insight you can provide!

Ashley

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

Ashley,

There are two issues you will run into.  The first one explains the results for &VAR4.

%if &a < &b < & c %then %do;

In macro language, expressions resolve from left to right.  This statement operates as if you had added parentheses:

%if (&a < &b) < &c %then %do;

Macro makes the first comparison, and replaces true comparisons with 1 and false comparisons with 0.  In your case, when &VAR4 is null, null is less then 0 so the first comparison is false.  The second comparison then becomes:  0 < 1 which is, of course, true.

The second issue you will encounter has to do with decimal points.  When macro language makes comparisons, it applies the %EVAL function.  %EVAL interprets decimal points as character strings.  Thus this comparison would also be true:

%if 39 < 4.0 %then %do;

As others have noted, %SYSEVALF can perform decimal fraction arithmatic.  This comparison would be false:

%if %sysevalf (39 < 4.0) %then %do;

Good luck.

View solution in original post

8 REPLIES 8
Reeza
Super User

This

0 < &&var&i < 1

type of logic doesn't work in macro world, you need to specify it as 0 < &&var&i  and &&var&i < 1


There's an explanation of why somewhere on here but I don't recall Smiley Happy

I think it resolves as 0<null = false then false<1 which is true rather than as vari between 0 and 1. 

Haikuo
Onyx | Level 15

Be careful when to use "0 < &&var&i < 1 ", in Macro, it will be interpreted as 0 < (&&var&i < 1). So anything that is less then 1 will be true, including those negative numbers.  Instead, breaking it up seems to be the safer way:

&&var&i  >0 and &&var&i < 1 

Haikuo

data_null__
Jade | Level 19

From the looks of those macro variable decimal values, I'm thinking you need to get %SYSEVALF involved.  Or better still don't use macro for this.

Haikuo
Onyx | Level 15

Absolutely.

"You must use the %SYSEVALF function to evaluate logical expressions containing floating-point or missing values."

SAS(R) 9.2 Macro Language: Reference

Fugue
Quartz | Level 8

You could do something as follows:

data _null_;

format x 9.3 y $4. z $50.;

do i=1 to 5 ;

x = symget('var'||left(i));

y = 'var'||left(i);

if ( 0 < x < 1 ) then do ;

  z = y || " is between 0 and 1";

  put z;

end ;

else do ;

  z = y || " is not between 0 and 1";

  put z;

end;

output;

end ;

run;

Astounding
PROC Star

Ashley,

There are two issues you will run into.  The first one explains the results for &VAR4.

%if &a < &b < & c %then %do;

In macro language, expressions resolve from left to right.  This statement operates as if you had added parentheses:

%if (&a < &b) < &c %then %do;

Macro makes the first comparison, and replaces true comparisons with 1 and false comparisons with 0.  In your case, when &VAR4 is null, null is less then 0 so the first comparison is false.  The second comparison then becomes:  0 < 1 which is, of course, true.

The second issue you will encounter has to do with decimal points.  When macro language makes comparisons, it applies the %EVAL function.  %EVAL interprets decimal points as character strings.  Thus this comparison would also be true:

%if 39 < 4.0 %then %do;

As others have noted, %SYSEVALF can perform decimal fraction arithmatic.  This comparison would be false:

%if %sysevalf (39 < 4.0) %then %do;

Good luck.

Haikuo
Onyx | Level 15

Bravo for the correct answer!

ashlicole
Obsidian | Level 7

Thank you, Astounding, for putting this so eloquently! The left-to-right logic makes perfect sense to me and i can now see the problem with this comparison!

P.S. thanks to all for the %SYSEVALF tip as well... i had actually sort of simplified/anonymized my code to post this question and hence the code i listed would not actually have worked without %SYSEVALF, but my real code was fine (other than that darn null macro variable!). thank you regardless for the feedback on that too.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 8 replies
  • 914 views
  • 8 likes
  • 6 in conversation