Search code examples
sasmacrossas-macro

Why is my %DO %UNTIL loop implemented even though the loop not satisfied the conditions in SAS MACRO PROGRAM?


I wrote the following SAS macro program code.

The purpose of the code is to repeat PROCREG while the condition(&maxVIFval > 1000) is satisfied.

However the %DO %WHILE loop is executed continually even though &maxVIFval has a value of 1000 or less.

I wonder what the reason is.

I'm looking for help..

Forgive my poor English.

%MACRO RegRepeat ; 

    %global maxVIFvar ;      /* maxVIFvar: global symbol table */ 
    %global maxVIFval ;      /* maxVIFval: global symbol table */ 
    %global j ;              /*     j    : global symbol table */ 
    %let maxVIFval = 10000 ;  
    %let j = 1 ;             
    
    %do %WHILE(  &maxVIFval > 1000  ) ; 
       
        /* Regression procedure below */
        PROC REG DATA=KNHANES.HNAP1319 ; 
            TITLE ; 
            TITLE "MAX VIF: &maxVIFval / Repeated Number: &j" ; 
            WEIGHT wt_pft_pool ; 
            WHERE HE_COPD = 3 ; 
            MODEL HE_fev1_new = SEX_new AGE OBE INCM_LH DJ4_dg_new sm1_former sm1_current at_risk_occp
                                &airPollution / lackfit ADJRSQ VIF  ; 
            ods output ParameterEstimates = PE ;
        RUN ; 
        
        /* SQL procedure below */
        PROC SQL ;
            CREATE TABLE WORK.maxVIF AS
            SELECT Variable, max(VarianceInflation) AS maxVIF
            FROM WORK.PE
            HAVING VarianceInflation = MAX(VarianceInflation) ; 
        QUIT ;
    
        /* DATA Step below */
        DATA WORK.maxVIFtoMV ;
            SET WORK.maxVIF ; 
            CALL SYMPUT("maxVIFvar", VARIABLE); 
            CALL SYMPUT("maxVIFval", maxVIF); 
        RUN ; 
        
        %let airPollution = %sysfunc(tranwrd(&airPollution, &maxVIFvar, )) ;
        %let j = %eval(&j+1) ;     
        %PUT MAX VIF: &maxVIFval / Repeated Number: &j ; 
   
    %end ;
    
%MEND ;

%RegRepeat 

These are sentences from the log window.

MPRINT(REGREPEAT): TITLE "MAX VIF: 10000 / Repeated Number: 1" ;

MPRINT(REGREPEAT): TITLE "MAX VIF: 1588.907368 / Repeated Number: 2" ;

MPRINT(REGREPEAT): TITLE "MAX VIF: 1297.8441436 / Repeated Number: 3" ;

MPRINT(REGREPEAT): TITLE "MAX VIF: 696.59402283 / Repeated Number: 4" ;

MPRINT(REGREPEAT): TITLE "MAX VIF: 569.83744288 / Repeated Number: 5" ;

Please let me know if you need any additional information.

Thank you for your kindness.


Solution

  • To fix this issue, use %sysevalf(&maxVIFval > 1000) to instead of &maxVIFval > 1000.

    When SAS compares two numbers in macro, it has different rules when numbers contain decimal point or not. When there is a decimal point, SAS treats numbers in macro as characters:

    %if 696.59402283>1000 %then %do;
      %put 0;
    %end;
    %else %do;
      %put 1;
    %end;
    
    0
    

    SAS compares characters char by char from left to right when comparing characters, "6" is larger than "1" in ascii code sequence, so we have 696.59402283>1000.

    When there are no decimal points, SAS treats numbers in macro as numbers:

    %if 696>1000 %then %do;
      %put 0;
    %end;
    %else %do;
      %put 1;
    %end;
    
    1
    

    The comparsion is based on mathmatical rules.

    I sugguest you always use %sysevalf() function if you want to do number comparsion in macro, unless you are 100% sure there are no decimal points.