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 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

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