whymath
whymath

Reputation: 1394

A better way to test if an macro variable is an valid SAS number or not

I am working on a SAS macro to validate if a macro variable is an valid SAS number or not. My solution is based on prxmacth() function:

%macro IsSASnumber(number);
%sysfunc(prxmatch(/^-?(?:\d+|\d*\.\d+)(?:e-?\d+)?|\.[a-z]?$/i,&number));
%mend;

There are several examples:

%put %IsSASnumber(123);
1

%put %IsSASnumber(1.23);
1

%put %IsSASnumber(-.12e-3);
1

%put %IsSASnumber(.N);
1

%put %IsSASnumber(.tryme);
0

My question is:

  1. Is this regular expression covers all condition?
  2. Is there a shorter or faster way to achieve this?

Ps: Assume the input is not empty.

Upvotes: 0

Views: 230

Answers (2)

Tom
Tom

Reputation: 51566

If the goal is to support using the INPUT() function without generating error messages when the strings do not represent numbers then just use the ? or ?? modifiers to suppress the errors.

Since the INPUT() function does not care if the width used on the informat specification is larger then the length of the string being read just use the maximum width the informat supports. So just use:

number = input(variable,??32.);

You might also want to test the length of VARIABLE, the numeric informat can only handle strings up to 32 bytes long. You might want to remove any leading spaces.

if length(left(variable)) <= 32 then number=input(left(variable),??32.);

If you want strings like "N" or "X" to be treated as meaning the special missing values .N and .X then make sure to tell SAS that in advance by using the global MISSING statement. To support all 27 special missing values use a missing statement like this:

missing abcdefghijklmnopqrstuvwxyz_ ;

If you want to treat '.N' as meaning .N instead of . then you will need to test for that string. To test all of them you could use something like:

if missing(number) and length(variable)=2 and char(variable,1)='.'
  then number=input(char(variable,2),??32.)
;

Note: make sure to use the name of an INFORMAT when using the INPUT() function. BEST is the name of a FORMAT (the name makes no sense as a name for an informat since there is only one way to represent a number as a number). If you use BEST as an INFORMAT SAS will just treat it as an alias for the normal numeric informat.

Upvotes: 1

Stu Sztukowski
Stu Sztukowski

Reputation: 12849

The %datatyp macro can determine all of these, but it fails at .N. You can simplify your use case this way:

%macro IsSASnumber(number);
    %sysevalf(%datatyp(&number) = NUMERIC OR %sysfunc(prxmatch(/^\.[A-Z_]$|^\.$/i, &number)));
%mend;

This will match your numeric cases, and then you can match the . cases.

Upvotes: 1

Related Questions