I want to create a function (in Macro terminology Macro?) that compares two numbers and returns the smaller one. This is one solution:
%macro Compare(x,y);
data test;
if &x > &y then ans = &y;
else if &x < &y then ans = &x;
else ans = &x; *They are equally big, does not matter which one I choose;
run;
proc print data=test;
%mend Compare;
What if I would like to compare two numbers and return the smalles one, BUT, if the numbers are equal return the answer "The numbers are equal". How would I do?
The alternative below does not work.
%macro Compare(x,y); data test; if &x > &y then ans = &y; else if &x < &y then ans = &x; else ans = 'The numbers are equally big'; * This does not work; run; proc print data=test; %mend Compare;
Thanks.
When you run into problems with a macro not working, you should run the command
options mprint;
and then run your macro again. This adds additional information into the LOG that can be used to diagnose the problem.
The log then looks like this:
165 %compare(7,7) MPRINT(COMPARE): data test; MPRINT(COMPARE): if 7 > 7 then ans = 7; MPRINT(COMPARE): else if 7 < 7 then ans = 7; MPRINT(COMPARE): else ans = 'The numbers are equally big'; MPRINT(COMPARE): * This does not work; MPRINT(COMPARE): run; NOTE: Character values have been converted to numeric values at the places given by: (Line):(Column). 1:82 NOTE: Invalid numeric data, 'The numbers are equally big' , at line 1 column 82. ans=. _ERROR_=1 _N_=1 NOTE: The data set WORK.TEST has 1 observations and 1 variables. NOTE: DATA statement used (Total process time): real time 0.01 seconds cpu time 0.01 seconds
Do you see the line that says:
NOTE: Invalid numeric data, 'The numbers are equally big'
This is the problem. Now, with that, can you figure out how to fix this?
In the end, this is not a macro problem at all. This is a DATA step error. This brings us to IMPORTANT ADVICE: first, write code that works without macros and without macro variables, and get that to work. You haven't done that. If it doesn't work without macros and without macro variables, then it will not work with macros and with macro variables. Please take my advice (which is also the advice of others) and create working DATA step code for this case which provides the desired result without macros and without macro variables. I'll even get you started:
data test;
x=7;
y=7;
if x>y ...
you write the rest and get it to work.
If you want to take the smaller of two numbers use the existing MIN() function.
%macro compare(x,y);
%sysfunc(min(&x,&y))
%mend compare;
%put The min of 5 and 6 is %compare(5,6);
If you are using a data step you can also use the min operator.
2269 data _null_; 2270 z = 5 >< 6 ; 2271 put z=; 2272 run; z=5
To write a macro:
%macro compare (x, y);
%if %sysevalf(&x > &y) %then %put &y is less.;
%else %if %sysevalf(&y > &x) %then %put &x is less.
%else %put The numbers are equal.;
%mend compare;
An few examples of calling the macro (you may not be interested in all of these forms):
%compare (6, 7)
%compare (5, 5)
%compare (3, 2.5)
%compare (3+3, 5)
These examples assume you really want a macro, and not code you would stick into a DATA step. For DATA step code, you would probably not use a macro.
/*https://www.sas.com/content/dam/SAS/support/en/sas-global-forum-proceedings/2018/2125-2018.pdf*/
libname fcmp 'D:\W\Code_lib\fcmp';
proc fcmp outlib=fcmp.test.small_num;
function get_small_num(num1,num2);
if num1>num2 then small=num2;
else small=num1;
return (small);
endsub;
quit;
option cmplib=fcmp.test;
data test;
input a b;
c=get_small_num(a,b);
cards;
1 2
2 3
;
run;
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!
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.
Ready to level-up your skills? Choose your own adventure.