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 lock in 2025 pricing—just $495!
Still thinking about your presentation idea? The submission deadline has been extended to Friday, Nov. 14, at 11:59 p.m. ET.
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.