# [racket] Decimal rounding problem

On 11/29/2012 07:55 AM, Matthew Flatt wrote:
>* At Thu, 29 Nov 2012 14:44:38 +0000, Greg Graham wrote:
*>* There are a couple of issues here.
*>*
*>* First, the inexact number 4.225 is actually slightly smaller than the
*>* exact value 4.225:
*>*
*>*[...]
*>*
*>* Even if you use the exact number 4.225, though, you get a "2" as the
*>* last digit:
*>*
*>* > (real->decimal-string #e4.225 2)
*>* "4.22"
*>*
*>* That's because rounding in Racket is to "even" --- a different
*>* convention than the one taught to most students, but one that it often
*>* preferred in computing (because it often reduces accumulated error, as I
*>* understand it).
*
Right. If you want to implement rounding with ties rounded away from
zero, you've got to do it yourself. Here's an implementation, which
takes an optional `scale' argument:
(define (round/ties-away x [scale 1])
(cond [(not (= scale 1)) (/ (round/ties-away (* x scale) 1) scale)]
[(x . < . 0) (truncate (- x 1/2))]
[else (truncate (+ x 1/2))]))
> (real->decimal-string (round/ties-away #e4.225 100) 2)
"4.23"
You'd still need to compute using exact numbers, though, because as
Matthew said, 4.225 is a little smaller than #e4.225:
> (real->decimal-string (round/ties-away 4.225 100) 2)
"4.22"
Also, multiplying and dividing inexact numbers by non-powers-of-two
introduces a little bit of error, which can make scaling before rounding
produce the wrong result. With exact numbers, though, it's, uh, exact.
Neil ⊥