IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

SAS approximation.


IBM Mainframe Forums -> All Other Mainframe Topics
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
vasanthz

Global Moderator


Joined: 28 Aug 2007
Posts: 1742
Location: Tirupur, India

PostPosted: Fri Jul 29, 2011 6:26 pm
Reply with quote

Hello,
I have a requirement in SAS to approximate values such that,
output value has to be first significant digit of input value + 1 and rest of the digits as 0's.
It is required for boundary values in GPLOT procedure.

Code:
Input:
20   
345   
5768 
987878
78   
211   
2000 

Output:
30     
400   
6000   
1000000
80     
300   
3000   


I tried,
Code:
DATA APPROX;                                                   
INPUT VAL;                                                     
IF VAL < 10 THEN VAL = VAL; ELSE                               
IF VAL < 100 THEN VAL = (INT(VAL/10)+1) * 10; ELSE             
IF VAL < 1000 THEN VAL = (INT(VAL/100)+1) * 100; ELSE         
IF VAL < 10000 THEN VAL = (INT(VAL/1000)+1) * 1000; ELSE       
IF VAL < 100000 THEN VAL = (INT(VAL/10000)+1) * 10000; ELSE   
IF VAL < 1000000 THEN VAL = (INT(VAL/100000)+1) * 100000; ELSE
IF VAL < 10000000 THEN VAL = (INT(VAL/1000000)+1) * 1000000;   
PUT VAL;                                                       
CARDS;                                                         
20                                                             
345                                                           
5768                                                           
987878                                                         
78                                                             
211                                                           
2000                                                           
;                                                             
RUN;     

Could you please let me know if there is any function or any other better method available to do this?

Thanks for viewing.
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8696
Location: Dubuque, Iowa, USA

PostPosted: Fri Jul 29, 2011 6:42 pm
Reply with quote

The one-line solution is:
Code:
     IF VAL <  0 THEN RSLT = .;
ELSE RSLT = (INT (VAL / 10 ** INT(LOG10(VAL)))+1) * 10 ** INT(LOG10(VAL)) ;
Back to top
View user's profile Send private message
vasanthz

Global Moderator


Joined: 28 Aug 2007
Posts: 1742
Location: Tirupur, India

PostPosted: Fri Jul 29, 2011 6:42 pm
Reply with quote

Correction:
This is wrong: IF VAL < 10 THEN VAL = VAL; ELSE
This is right : IF VAL < 10 THEN VAL = 10; ELSE
Back to top
View user's profile Send private message
vasanthz

Global Moderator


Joined: 28 Aug 2007
Posts: 1742
Location: Tirupur, India

PostPosted: Fri Jul 29, 2011 6:50 pm
Reply with quote

Thanks Robert,
Code:
 RSLT =                                                       
(INT (VAL / 10 ** INT(LOG10(VAL)))+1) * 10 ** INT(LOG10(VAL)) ;

Works Great! icon_biggrin.gif

Although hard for my brain to comprehend.
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8696
Location: Dubuque, Iowa, USA

PostPosted: Fri Jul 29, 2011 6:52 pm
Reply with quote

Just add an ELSE IF to my code before the ELSE RSLT to get it to do what you want.

It is very bad practice to wipe out your initial value with the computed value the way your code does. Creating a new variable is not a big deal to SAS, and sometimes it helps in debugging to see both the original and computed values.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Fri Jul 29, 2011 6:56 pm
Reply with quote

I'd always liks an "ELSE, Rats, I didn't think the number could be that big" at the end.

As the numbers get bigger, you have an ever bigger range which ends up with one value. If that is what you need, OK by me.

I'd not be too worried about the code. It is clear what you are doing, and it will work.

You could put you limit values in an "array" and do a bit of looping. This would save on repetition in the statements, so there'd only be one value to type correctly for each band.

If there is a function that will do it, I'm sure Robert will come up with it :-)

It would be the neatest way, but obviously it relies on the existence of a function that does what you want.

Can you make your own functions? However, likelihood will be a repeat of the existing chosen method in the function.

I have no idea if you can get at the definition of the data, and loop looking for the first non-zero, add 1 (of course, catering for the value being 9) and then zeroise to the end of the piece of data.

I suppose the question is, what is it about your approach that you have concerns about?
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8696
Location: Dubuque, Iowa, USA

PostPosted: Fri Jul 29, 2011 6:58 pm
Reply with quote

Quote:
Although hard for my brain to comprehend.
I guess being a math major in college does help sometimes.

The LOG10 function in SAS returns the base-10 logarithm of a number. The integer part of the logarithm is the power of 10 -- 0 means 1, 1 means 10, 2 means 100, 3 means 1000, and so forth. Divide a number by 10 raised to that power and you get a value between 1 and 10 with a fraction. The integer part is taken and 1 added to it. Then multiply by the power of 10 to get that value back to the original size.
Back to top
View user's profile Send private message
expat

Global Moderator


Joined: 14 Mar 2007
Posts: 8797
Location: Welsh Wales

PostPosted: Fri Jul 29, 2011 7:03 pm
Reply with quote

Couldn't you have also considered using formats ?
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8696
Location: Dubuque, Iowa, USA

PostPosted: Fri Jul 29, 2011 7:13 pm
Reply with quote

Yes -- PROC FORMAT would allow some code like
Code:
RLST = PUT(VAL, UPDTVAL.) ;
where UPDTVAL is the PROC FORMAT variable, although the add 1 piece would need to be added.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Fri Jul 29, 2011 7:14 pm
Reply with quote

Gosh, Robert, long before I finished typing (I must speed up). Even deals with the bigger numbers that could be unexpected.

A masterpiece.

Vasanthz, I didn't understand it either, until Robert explained. Document it, with what you are trying to achieve and with Robert's explanation. Don't just leave it sitting there working. Next one along (could be you) will be flumoxed by it, until checking everything through - would be a couple of wasted hours.
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8696
Location: Dubuque, Iowa, USA

PostPosted: Fri Jul 29, 2011 7:27 pm
Reply with quote

Thanks, Bill. I even tested it before posting to make sure I had the parentheses right.
Back to top
View user's profile Send private message
vasanthz

Global Moderator


Joined: 28 Aug 2007
Posts: 1742
Location: Tirupur, India

PostPosted: Fri Jul 29, 2011 7:28 pm
Reply with quote

Robert,
Thanks for the detailed explanation. I have some understanding of the formula. Will try then out in parts to get a clearer picture.
Quote:
bad practice to wipe out your initial value with the computed value the way your code does.

Point taken.
Quote:
loop looking for the first non-zero, add 1 (of course, catering for the value being 9) and then zeroise to the end of the piece of data.

Hello Bill,
One thing I noticed in using SAS is, if something is repititive or even a little complex, then probably SAS has some built in function or a better method to do it. So posted the requirement, to see if there is an alternative available.
Quote:
Can you make your own functions?

Yep, but then again we have to write the computational logics for functions.
Quote:
what is it about your approach that you have concerns about?

I thought my approach was sloppy with repititive coding and probability of input value to exceed the condition being checked :S
Quote:
Couldn't you have also considered using formats ?

Oh PROC FORMAT.! forgot about it completely. Thanks Expat.

Thank you all.
Back to top
View user's profile Send private message
vasanthz

Global Moderator


Joined: 28 Aug 2007
Posts: 1742
Location: Tirupur, India

PostPosted: Fri Jul 29, 2011 7:47 pm
Reply with quote

Quote:
Document it, with what you are trying to achieve and with Robert's explanation. Don't just leave it sitting there working. Next one along (could be you) will be flumoxed by it, until checking everything through

I always document code as if the person who is going to maintain the code is a maniac serial killer who knows where I live (:
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8696
Location: Dubuque, Iowa, USA

PostPosted: Fri Jul 29, 2011 7:56 pm
Reply with quote

Quote:
I always document code as if the person who is going to maintain the code is a maniac serial killer who knows where I live
I like this ... I really like this! icon_biggrin.gif
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Fri Jul 29, 2011 7:58 pm
Reply with quote

Excellent. I won't tell the people who aren't my guys to warn the serial killer off.
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> All Other Mainframe Topics

 


Search our Forums:

Back to Top