[racket] Decimal rounding problem
On 11/29/2012 10:53 AM, Greg Graham wrote:
> Thank you to everyone who weighed in on the topic; the discussion has been very informative and interesting.
>
> I've decided to not do the rounding in Racket, but to store all of the digits in the database. The rounding will occur at the time of display by either Crystal Reports or Excel, which is what the current system does anyway. That way we won't see any unexpected changes in anyone's GPAs.
>
> Now, the unanswered question is why do Crystal Reports and Excel round 4.225 to 4.23? I don't think I'll find as helpful of a forum to answer that question as I have found for Racket. Thanks again for being such a great community!
Aw, you buttered us up so nicely that I have to respond. They're
probably rounding twice: once to get a decimal number close to the
original, and then to the specified number of digits. This'll do it:
(define (smart-donkey-round x [scale 1])
(cond [(inexact? x)
(smart-donkey-round (smart-donkey-round (inexact->exact x)
(expt 10 14))
scale)]
[(not (= scale 1))
(/ (smart-donkey-round (* x scale) 1) scale)]
[(x . < . 0)
(truncate (- x 1/2))]
[else
(truncate (+ x 1/2))]))
> (real->decimal-string (smart-donkey-round 4.225 100) 2)
"4.23"
The magic number (expt 10 14) is the reciprocal of the assumed error
when `x' is inexact. Flonums have about 15 digits precision.
Neil ⊥