BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
AndersS
Lapis Lazuli | Level 10

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

Anders Sköllermo (Skollermo in English)
1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

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;

Tom_0-1762615571722.png

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)));

View solution in original post

6 REPLIES 6
quickbluefish
Barite | Level 11
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;
AndersS
Lapis Lazuli | Level 10
Hi! Yes this solves the simple example problem.
BUT next level - decimal numbers.
Third level: A mix of Relative and Absolute rounding.
Anders Sköllermo (Skollermo in English)
Tom
Super User Tom
Super User

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;

Tom_0-1762615571722.png

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)));
AndersS
Lapis Lazuli | Level 10

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

Anders Sköllermo (Skollermo in English)
ballardw
Super User

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.

AndersS
Lapis Lazuli | Level 10
Hi! Good question about the comma. You are quite right. /Br AndersS
Anders Sköllermo (Skollermo in English)
How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 6 replies
  • 295 views
  • 5 likes
  • 4 in conversation