I was curious to know if there is some sas function that can convert a value of a character variable ("1/3"), to a numeric variable (.333333...). This would save me the trouble of parsing out the different parts of "1/3" into intermediate variables to then use conditional statements to do the calculation.
It would be nice if input("1/3",8.) would give you .33333
Not aware of an Informat, which would be the likely took, that would do this.
If the data is "clean" the parse and calculate in pretty simple:
data example; input x $; if index(x,'/')>0 then number = input(scan(x,1,'/'),12.)/input(scan(x,2,'/'),12.); datalines; 1/3 10/31 4.5 3.555/17.44 ;
The above only does the division when there is a / and a non-fraction value is provided to demonstrate that.
If you have more than one / in the string you're on your own.
Not aware of an Informat, which would be the likely took, that would do this.
If the data is "clean" the parse and calculate in pretty simple:
data example; input x $; if index(x,'/')>0 then number = input(scan(x,1,'/'),12.)/input(scan(x,2,'/'),12.); datalines; 1/3 10/31 4.5 3.555/17.44 ;
The above only does the division when there is a / and a non-fraction value is provided to demonstrate that.
If you have more than one / in the string you're on your own.
thanks, but I was curious to know if there is an easier way than that. Something specifically designed to resolve all manner of arithmetic formulas that could be in a character variable. Some one function like the input function. Also something not involving macros.
No.
IF the string is just pure arithmetic, like your example, then you could use %sysevalf() macro function.
data have;
input equation $20.;
cards;
1/3
1+1/2
;
data want;
set have;
number=input(resolve(cats('%sysevalf(',equation,')')),32.);
run;
proc print;
run;
Obs equation number 1 1/3 0.33333 2 1+1/2 1.50000
If you also have other strings that might be numbers you might also try using the COMMA informat (the "best" informat).
data have;
input equation $20.;
cards;
1/3
1+1/2
25%
1,234
;
data want;
set have;
number=input(equation,??comma32.);
if missing(number) then
number=input(resolve(cats('%sysevalf(',equation,')')),32.)
;
run;
Thanks. Something like this is what I was interested in. I don't have anything against macros or macro variables. I want the formulas to be values in a dataset variable, not in a macro variable.
I was just wondering about a unit conversion dataset I was recently looking at. Some of the factors may be truncated decimals from the division of two numbers where the decimals go on to infinity. I was wondering if instead of specifying the truncated result, to just put in the formula and have sas figure out what it resolves to.
@Anthony_de_Fex wrote:
Thanks. Something like this is what I was interested in. I don't have anything against macros or macro variables. I want the formulas to be values in a dataset variable, not in a macro variable.
I was just wondering about a unit conversion dataset I was recently looking at. Some of the factors may be truncated decimals from the division of two numbers where the decimals go on to infinity. I was wondering if instead of specifying the truncated result, to just put in the formula and have sas figure out what it resolves to.
You might look in the documentation of Proc Format that uses a formula stored in a function created by Proc Fcmp to do unit conversions. The example in the documentation shows a Fahrenheit to Celsius and vice versa temperature conversion. These allow putting the division as 1/3 if needed as the Fcmp function would use typical syntax for numeric computation. If the conversion has ranges involved the functions allow testing one or more of the parameters passed to execute the appropriate section of code.
https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.4/proc/p1gg77jyhc9s42n1f1vjyx2hsg8b.htm
Caveat: If you use these formats you need to make the functions and the formats available to the SAS session. Also do not lose the code to create them. You will likely need to rebuild both the function and the format in later versions of SAS as the format catalog alone may not be sufficient in later software.
@Anthony_de_Fex wrote:
Also something not involving macros.
A pointless limitation. Why do you want to avoid macros?
(And technically, no one has proposed a macro solution; what has been proposed is a solution using a macro variable, which is not the same as a macro; or using a macro function %sysevalf, which is not the same as a macro)
If the character string is a syntactically correct statement, put it into a macro variable, and then after that in a DATA step you can do
input(¯ovarname,best16.)
Hi.
Try this:
data Test;
informat String $10.;
input String;
Position = findc(String,'/');
if Position then do;
put _all_;
Numerator = substr(String,1,Position-1);
Denominator = substr(String,Position+1);
Number = input (Numerator,10.) / input(Denominator,10.);
end;
else number = input(String,10.);
datalines;
1/3
2/5
8
;
title "Listing of Test";
proc print data=Test;
run;
Please check out support.sas.com/Cody to see some of my SAS programming books.
Hi Ron. Thanks for your answer, but that is too much for what I had in mind. I like the input(resolve(cats('%sysevalf(',equation,')')),32.); from the other user.
I've read some of your books by the way, like 20 years ago.
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.