round?
[1/4] from: yogi:helimail at: 1-Dec-2001 2:06
Hello,
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.
Any hint?
cu, yogi
[2/4] from: tomc:darkwing:uoregon at: 30-Nov-2001 17:25
there was recently a fairly complete discussion on rounding
it should be findable on the archive
http://www.escribe.com/internet/rebol/search.html?query=round
On Sat, 1 Dec 2001, Marc Michael wrote:
[3/4] from: lmecir:mbox:vol:cz at: 1-Dec-2001 2:31
Try e.g. http://www.sweb.cz/LMecir/rounding.r
Regards
Ladislav
----- Original Message -----
From: Marc Michael <[yogi--helimail--de]>
To: REBOL-Mailingliste <[rebol-list--rebol--com]>
Sent: Saturday, December 01, 2001 2:06 AM
Subject: [REBOL] round?
Hello,
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.
Any hint?
cu, yogi
[4/4] 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.
; Ladislav Mecir, Gregg Irwin (minor adjustment)
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
; (read interval) of 30.
; Ladislav Mecir, Gregg Irwin
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][1]]
factor: either places [
10 ** (negate pl)
][
either to-interval [interval][1]
]
;-- 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
Librarian comment
A round function now exists in all versions of REBOL since the middle of 2005.