View previous topic :: View next topic
|
Author |
Message |
vasanthz
Global Moderator
Joined: 28 Aug 2007 Posts: 1742 Location: Tirupur, India
|
|
|
|
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 |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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 |
|
|
vasanthz
Global Moderator
Joined: 28 Aug 2007 Posts: 1742 Location: Tirupur, India
|
|
|
|
Correction:
This is wrong: IF VAL < 10 THEN VAL = VAL; ELSE
This is right : IF VAL < 10 THEN VAL = 10; ELSE |
|
Back to top |
|
|
vasanthz
Global Moderator
Joined: 28 Aug 2007 Posts: 1742 Location: Tirupur, India
|
|
|
|
Thanks Robert,
Code: |
RSLT =
(INT (VAL / 10 ** INT(LOG10(VAL)))+1) * 10 ** INT(LOG10(VAL)) ; |
Works Great!
Although hard for my brain to comprehend. |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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 |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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 |
|
|
expat
Global Moderator
Joined: 14 Mar 2007 Posts: 8797 Location: Welsh Wales
|
|
|
|
Couldn't you have also considered using formats ? |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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 |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
Thanks, Bill. I even tested it before posting to make sure I had the parentheses right. |
|
Back to top |
|
|
vasanthz
Global Moderator
Joined: 28 Aug 2007 Posts: 1742 Location: Tirupur, India
|
|
|
|
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 |
|
|
vasanthz
Global Moderator
Joined: 28 Aug 2007 Posts: 1742 Location: Tirupur, India
|
|
|
|
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 |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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! |
|
Back to top |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
Excellent. I won't tell the people who aren't my guys to warn the serial killer off. |
|
Back to top |
|
|
|