Mailing List Archive: 49091 messages

## [REBOL] Re: round?

### From: greggirwin::mindspring::com at: 30-Nov-2001 21:28

```
Hi Yogi,

<< exists a function in Rebol to round a decimal value?
I have searched the documentaion with the word "round", but
i don't found anything. >>

Here's what I built up around Ladislav's work, based on the recent
discussions here on the ML. Watch out for line breaks.

mod: func [
{Compute a remainder.}
value1 [number! money! time!] {The dividend}
value2 [number! money! time!] {The divisor}
/euclid {Compute a non-negative remainder such that: a = qb + r and
r < b}
/local r
] [
either euclid [
either negative? r: value1 // value2 [r + abs value2] [r]
][
value1 // value2
]
]

;-- Note: to-interval does mod-like rounding. If the interval you
;         specify is not evenly divisble into your base, the result
;         may not be what you expect. E.g. round/to-interval 133 30
;         will round to 120, not 130, because 120 is an even multiple
round: func [
value [number! money! time!] {The value to round}
/up         {Round away from 0}
/floor      {Round towards the next more negative digit}
/ceiling    {Round towards the next more positive digit}
/truncate   {Remaining digits are unchanged. (a.k.a. down)}
/places     {The number of decimal places to keep}
pl [integer!]
/to-interval {Round to the nearest multiple of interval}
interval [number! money! time!]
/local
factor
][
;-- places and to-interval are redundant. E.g.:
;       places 2 = to-interval .01
;   to-interval is more flexible so I may dump places.
;-- This sets factor in one line, under 80 chars, but is it clearer?
;factor: either places [10 ** (- pl)][either to-interval
[interval]]
factor: either places [
10 ** (negate pl)
][
either to-interval [interval]
]
;-- We may set truncate, floor, or ceiling in this 'if block.
if not any [up floor ceiling truncate] [
;-- Default rounding is even. Should we take the specified
;   decimal places into account when rounding? We do at the
;   moment.
either (abs value // factor) <> (.5 * factor) [
value: (.5 * factor) + value
return value - mod/euclid value factor
][
;-- If we get here, it means we're rounding off exactly
;   .5 (at the final decimal position that is).
either even? value [
truncate: true
][
either negative? value [floor: true][ceiling: true]
]
]
]
if up       [either negative? value [floor: true][ceiling: true]]
if truncate [return value - (value // factor)]
if floor    [return value - mod/euclid value factor]
if ceiling  [return value + mod/euclid (negate value) factor]
]

--Gregg
```