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 ⊥
Alternatively, you can understand it in terms of how many flonums there
are between each integer. That number decreases as the numbers get
farther from zero:
> (require unstable/flonum) ; (require math/flonum) on the nightlies
> (flonums-between 2.0 3.0)
2251799813685248
> (flonums-between 4.0 5.0)
1125899906842624
It gets really sparse, eventually:
> (flonums-between (expt 2.0 52.0) (+ (expt 2.0 52.0) 1.0))
1
Neil ⊥
Robby
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 ⊥
In octal you have the same issue, how do you round octal 0.4 ?
No, we should be using an odd base, say base-5. Fingers and thumb of one hand. No central digit to cause rounding ambiguity.
Stephan
Stephan Houben