Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- Home
- /
- Programming
- /
- SAS Procedures
- /
- Creating a format which rounds to even

Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

🔒 This topic is **solved** and **locked**.
Need further help from the community? Please
sign in and ask a **new** question.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Posted 11-21-2016 07:18 AM
(4579 views)

Hello,

I need to create a format which formats to 2 decimal places whilst rounding to the nearest even number i.e. it will print the number 8.665 as 8.66 rather than 8.67.

I have begun by following the advice in this thread and created a custom format which uses a function to do the format. What I have so far is this..

```
proc fcmp outlib=work.func.sample;
function nre(value);
return( rounde(value, 0.01) );
endsub;
run;
* make function available;
options cmplib=work.func;
* create a format that uses the function;
proc format;
value rex
low - high = [nre()]
;
run;
```

The problem I have is that my custom format rex will round correctly but will not display to two decimal places i.e. it drops trailing zeroes and prints 4.00 as 4. Any help in getting to the final step would be much appreciated.

Also, right now I only need to perform this to two decimal places but often need to round to an arbitrary number of places. Is there a way to generalise this code to allow me to select the number of places to round to without having to create a newformat

Thanks,

Steve

1 ACCEPTED SOLUTION

Accepted Solutions

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

How about something like this, which gives you more control over the formatted value as a displayed value.

```
proc fcmp outlib=work.func.sample;
function nre(value) $;
return( put(rounde(value, 0.01),5.2) );
endsub;
run;
* make function available;
options cmplib=work.func;
* create a format that uses the function;
proc format;
value rex
low - high = [nre()]
;
run;
data n;
length x 8 y 8 z 8;
x = 4.00;
y = 4.536;
z = 1.625;
format x rex. y rex. z rex.;
run;
```

Obs x y z 1 4.00 4.54 1.62

10 REPLIES 10

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Why not use the round function?

Try round( variable, **0.02**);

If you really want a format check the SAS docs about creating a format based on a function. There's an example in the docs.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

The bigger picture is that I'm trying to format values as they come out of a PROC TABULATE procedure without having to put them through another data step. Normally this is something I would do in the data step but constraints on this particular project means I'd like to do to this with format.

Also I'm not sure I agree that this constitutes bad practice or obfuscating the data underneath. After all, SAS is already rounding the value it presents when using the w.d format I would normally use. All I'm trying to do is make SAS use a different rounding method.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Hi,

Rounding is a different concept to formatting, maybe the terminology you use means something different? To round a number, you take the value and physically change that value in the dataset. Formatting a variable does not physically change the value, only the way it is displayed. So:

Actual value = 1.36

Rounded value = 1.4

Formatted value (as shown in table view) = 1.3

Actual value if format is removed = 1.36

I rarely use tabulate if at all any more, so can't really help much with syntax there, but you get a table out from your statement do you not, or does that goto an output file directly?

Seems to me like your saving on a couple of lines of data step code after the effect, but vastly expanding your code to encompass formats, and functions etc.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Hi,

I think you are right that we are talking about different types of rounding.

What I might call "data rounding" is when you change the value of the underlying value using a round function. So for example if x = 1.625, then rounde(x,0.01) = 1.620.

What I might call "format rounding" is the rounding that SAS applies to the value it displays whilst keeping the underlying value the same.

So if I have a value of 1.625 and apply the 6.2 (the w.d format), then SAS will display this as 1.63 whilst the underlying value of 1.625 is retained. So SAS has "Format rounded" the formatted value of 1.625 to 1.63.

What I want to do is choose the type of rounding SAS does to the formatted value. By default SAS rounds up (1.625 -> 1.63) but I want it to round to even (1.625 -> 1.62).

The benefit of this is I could present the data in the way I need without changing the underlying value. Otherwise I would need to

1) Use Proc tabulate to create the table and output it as a data set.

2) Use a data step to round all the values using the rounde function

3)Use Proc report to output this dataset to a PDF.

What I want to do is

1) Use proc tabulate to create the PDF directly with the values already rounded the correct way.

Hope this clarifies what I am trying to do. Thanks for your input so far.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

How about something like this, which gives you more control over the formatted value as a displayed value.

```
proc fcmp outlib=work.func.sample;
function nre(value) $;
return( put(rounde(value, 0.01),5.2) );
endsub;
run;
* make function available;
options cmplib=work.func;
* create a format that uses the function;
proc format;
value rex
low - high = [nre()]
;
run;
data n;
length x 8 y 8 z 8;
x = 4.00;
y = 4.536;
z = 1.625;
format x rex. y rex. z rex.;
run;
```

Obs x y z 1 4.00 4.54 1.62

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Thanks!

I've been able to use this code as a basis to create a set of formats rounding evenly to different decimal places, which should save me a lot of time in the future.

In answer to some of the other questions, rounding to even only applies in the case of tie breakers e.g. the third decimal place is 5 when your rounding to 2d.p.

Therefore 1.615-> 1.62, 1.625->1.62. All other cases would be rounded as you would normally expect, so 1.633->1.63.

From what I know, rounding to even is the statistically safer way of rounding. It is also the way R rounds by default which is why I need to achieve the same in SAS.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

What you gonna do with odd number like : 1.633 ?

```
proc format;
picture rex
other='009.99' ;
run;
data n;
length x 8 y 8 z 8;
x = 4.00;
y = 4.536;
z = 1.625;
format x y z rex.;
run;
```

Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.

**If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website. **

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

Find more tutorials on the SAS Users YouTube channel.