Conditionally Set Macro Variable Embedded in Macro

Reply
New Contributor
Posts: 4

Conditionally Set Macro Variable Embedded in Macro

[ Edited ]

Hi All!

 

The below macro will conditionally set the macro variables &r1 and &r2 to either 0 or 1 based on the following criteria, where &sub. is a random number (which was generated by another macro variable).

if &sub. is a whole number  then r1=0 and r2 = 0

if &sub. has a decimal that rounds down then r1 = 1 and r2 = 0

if &sub. has a decimal around rounds up then r1 =1 and r2=1

 

However, i can't get the macro to work. When i use this macro i get the error message "Statement is not valid or is used out of proper order". Any tips?

 

%macro round_test (sub);
%let r1 = x;
%let r2 = y;
%let round = %eval(%sysfunc(int(&sub.))-&sub.);
%if &round = 0 %then %do;
          x=0;
          y=0;
%end;
%else %if round(&round) = 0 %then %do;
          x=1;
          y=0;
%end;
%else %do;
         x=1;
         y=1;
%end;
run;
%mend;

 

Hey Guys, I beleive i solved this with the below code:

 

%macro round_test (sub);
%let round = %eval(%sysfunc(int(&sub.))-&sub.);
%if &round = 0 %then %do;
      %let r1=0;
      %let r2=0;
%end;
%else %if round(&round) = 0 %then %do;
     %let r1=1;
      %let r2=0;
%end;
%else %do;
      %let r1=1;
      %let r2=1;
%end;
run;
%mend;

Super User
Posts: 6,785

Re: Conditionally Set Macro Variable Embedded in Macro

You are getting closer.  However, note that:

 

%EVAL cannot use decimal points, let alone decimal fractions.  Use %SYSEVALF instead if you want the math to be performed on decimal fractions.

 

Macro language does not understand the ROUND function.  Apply %SYSFUNC to the ROUND function, to let macro language execute the DATA step version of the function.

Super User
Super User
Posts: 8,120

Re: Conditionally Set Macro Variable Embedded in Macro

[ Edited ]

Why are you manipulating floating point numbers in macro variables?  If you do then make sure to use %sysevalf() instead of the default %eval().

 

Looks like you want something like this.

Make sure to define ROUND, R1 or R2 before you call the macro if you want to use the value after the macro ends.

%macro round_test (sub);
%local sign ;
%let round = %sysfunc(round(&sub));
%let sign = %sysfunc(sign(&round-&sub));
%let r1=%eval(&sign^=0);
%let r2=%eval(&sign=1);
%put &=sub &=round &=sign &=r1 &=r2 ;
%mend;
518  %round_test(1);
SUB=1 ROUND=1 SIGN=0 R1=0 R2=0
519  %round_test(1.1);
SUB=1.1 ROUND=1 SIGN=-1 R1=1 R2=0
520  %round_test(1.9);
SUB=1.9 ROUND=2 SIGN=1 R1=1 R2=1

 If you are going to use it on negative numbers then test those also to make sure if does what you want in that case.

Ask a Question
Discussion stats
  • 2 replies
  • 73 views
  • 0 likes
  • 3 in conversation