I have a question: What tools are there in the Data-step make a Relative Rounding of a numeric number?
I know about the ROUND, ROUNDE and ROUNDZ functions.
But they make an Absolute rounding.
Example:
Population is some countries:
345,123456
34,123456
3,123456
123456
23456
But the user rather wants relative rounding to e.g.3 digits, like
345,000000
34,100000
3,120000
123000
23400
(Yes I have some ideas about to achieve this - if it is not already solved.
Please omit any misprint - Some Covid-19 look alike here)
/Br Anders Sköllermo - Skollermo in English
If you want to keep N digits for any magnitude number then first use LOG10() to figure out the magnitude of the number. Then you can adjust the factor your multiple/divide by in that formula.
So if you set the macro variable NDIGITS to represent the number of digits you want to keep the formula could be:
factor = 10 ** (floor(log10(X))-(&ndigits-1));
X_round=round(X/factor)*factor;
Example;
%let ndigits=3;
data test;
input n;
log=floor(log10(n));
factor = 10 ** (log-(&ndigits-1));
n_round=round(n/factor)*factor;
cards;
345123456
34512345
3451234
345123
34512
3451
345.1
34.51
3.451
.3451
.03451
.003451
;
proc print;
format n best20.3 n_round comma20.6 ;
run;
Note you can skip the multiplication and division and just let the ROUND() function do it for you by using the optional second argument.
n_round=round(n,10 ** (floor(log10(n))-(&ndigits-1)));
data test;
input n;
cards;
345123456
34123456
3123456
123456
23456
;
run;
data want;
set test;
n_round=round(n/1000)*1000;
run;
proc print data=want; run;
If you want to keep N digits for any magnitude number then first use LOG10() to figure out the magnitude of the number. Then you can adjust the factor your multiple/divide by in that formula.
So if you set the macro variable NDIGITS to represent the number of digits you want to keep the formula could be:
factor = 10 ** (floor(log10(X))-(&ndigits-1));
X_round=round(X/factor)*factor;
Example;
%let ndigits=3;
data test;
input n;
log=floor(log10(n));
factor = 10 ** (log-(&ndigits-1));
n_round=round(n/factor)*factor;
cards;
345123456
34512345
3451234
345123
34512
3451
345.1
34.51
3.451
.3451
.03451
.003451
;
proc print;
format n best20.3 n_round comma20.6 ;
run;
Note you can skip the multiplication and division and just let the ROUND() function do it for you by using the optional second argument.
n_round=round(n,10 ** (floor(log10(n))-(&ndigits-1)));
Hi! VERY nice solution.
I had an idea of using PUT and SUBSTR.
I will have a look at this nice solution and my own (unfinished) work.
Nice discussions! /Br Anders Sköllermo - Skollermo in English
I have a silly (?) question: why do you only have one comma in 345,123456 and several other of your example values? Normally when I see a single comma in a value with that many digits I have to assume comma is from one of the languages that uses a comma for separating the decimal and a . for the thousands separator.
Another approach would be use a custom format with differing digit selectors based on range of values but that would normally have multiple commas in those values.
April 27 – 30 | Gaylord Texan | Grapevine, Texas
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and save with the early bird rate—just $795!
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.