Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: ROUND function (like TRUNC, FLOOR, etc...)

From: riusa:email:it at: 18-Feb-2002 9:17

First of all: thank you for the function! after this... a curiosity: why Rebol does not implement native round functions? ======================================================
> << I'm developing a program in my company, and an engineer asked how I > round the numbers... but... I discovered (I'm still a newbie...) Rebol > has only TO-INTEGER function to round a number! No FLOOR, no CEIL, no > TRUNC! > > And... how about Banker's algorithm to round numbers? >> > > Here's what I came up with, based on some of Ladislav's excellent
work.
> Watch for word-wrap. > > ; 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] > ;-- Alternate implementation > ;value1 // value2 + (value2: abs value2) // value2 > ][ > 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 [ > {Rounds numeric value with refinements for what kind of
rounding
> you want performed, how many decimal places to round to,
etc.}
> 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] > ] > > HTH! > > --Gregg >
-- Prendi GRATIS l'email universale che... risparmia: http://www.email.it/f Sponsor: In questo momento di incertezza il modo sicuro per mandarti in vacanza lo abbiamo trovato noi Invitaci, e ti spiegheremo tutto. Clicca qui: http://adv.email.it/cgi-bin/foclick.cgi?mid=271&d=18-2