Re: st: RE: rounding in STATA

 From "Austin Nichols" <[email protected]> To [email protected] Subject Re: st: RE: rounding in STATA Date Thu, 13 Apr 2006 10:15:16 -0400

```Amani--

All of what Nick says is true, but the claim that "there is no way you
can avoid this kind of problem by writing your own program, unless you
also construct a decimal-based computer" is overreaching a bit. It's
true that the general problem of numerical precision is unavoidable,
but the specific problem you want to address is not.  If you want to
force the incorrect behavior you seem to want (rounding 8.64999999999
to 8.7) there is a way to do it.  If you are representing your numbers
as having 2 digits after the decimal point, and you believe that such
a representation is true and the more accurate binary representation
is not, then you can force the rounding you want by treating your
representation as a string--but you could be introducing error in any
binary-based rounding done by your computer.

. clear
. set obs 100
. gen obs=_n/100
. gen real=round(obs, .1)
. gen silly=round(real(string(obs*100, "%4.0f")),10)/100
. li in 64/66

+--------------------+
| obs   real   silly |
|--------------------|
64. | .64     .6      .6 |
65. | .65     .6      .7 |
66. | .66     .7      .7 |
+--------------------+

Your original post raises the question of how you got the numerical
8.75 so that you know the decimal representation is exact, but the
computer doesn't (did you do a whole series of calculations that
should result in exactly 35/4 but instead results in a close, but not
close enough, approximation?)  If so, you can turn your calculation on
integers like X into calculations using integers by using an
appropriate factor, such as 4X or 40X or 100X, and get the "right"
answer (but the appropriate factor to apply before and after the
intermediate calculations to preserve accuracy will depend on what the
intermediate calculations are).  Bear in mind always that

. di round(35/4,.1)
8.8

gives you the answer you seem to want, and you should be able to get
there from here.

--Austin

On 4/13/06, Nick Cox <[email protected]> wrote:
> I can't speak about STATA. In Stata, which behaves
> similarly in this instance, you can get rounding up
> by using -ceil()-.
>
> But note that you will find it difficult to avoid
> small (apparent) anomalies whatever you do.
>
> This because, in general, multiples of 0.1 cannot
> be held exactly in binary, as explained many, many
> times on this list.
>
> Suppose I have 8.75 (meaning, precisely, 8 + 3/4).
>
> Stata can hold that, _exactly_. In decimal,
>
> . di %23.18f 8.750
>    8.750000000000000000
>
> or, more to the point, in hexadecimal,
>
> . di %21x 8.750
> +1.1800000000000X+003
>
> If I round that, Stata starts to struggle:
>
> . di %21x round(8.750, 0.1)
> +1.199999999999aX+003
>
> . di %23.18f round(8.75,0.1)
>    8.800000000000000700
>
> This raises the question of what, exactly, is
> the number you are showing us which is (which
> is represented as!) 8.750. Your number is,
> I surmise, not exactly 8.750, as if it were
> it would round to 8.8.
>
> That said, there is no way you can avoid this kind of
> problem by writing your own program, unless
> you also construct a decimal-based computer.
>
> Nick
> [email protected]
>
> Siyam, Amani
>
> > I have a minor issue with the way STATA is rounding, for example a
> > variable to one decimal place.
> >
> > I used the command
> >
> > gen x=round(y, 0.1)
> >
> > Comparing the two variables, I noticed the that when:
> >
> >    x=                   y=
> >
> >  8.750                 8.7
> >  5.752                 5.8
> > 23.256                23.3
> >
> > Is there a way I can modify the function to round "x"=8.750 to be 8.8
> >
> > Or should I put together my own code to get the rounding I want.

*
*   For searches and help try:
*   http://www.stata.com/support/faqs/res/findit.html
*   http://www.stata.com/support/statalist/faq
*   http://www.ats.ucla.edu/stat/stata/
```