Rounding
[1/7] from: mat:0wnerage at: 29-May-2002 18:54
Folks,
>> print to-integer 1.6
1
I can't for the life of me find a word which does the same as this but
which actually rounds (so you'd get 2) rather than just chopping off
the remainder.
Is there such a beast or must one write a function to do it?
I've actually resorted to doing exactly this and it's pretty ugly :)
Regards,
Mat
[2/7] from: greggirwin:mindspring at: 29-May-2002 12:57
Hi Mat,
Here's a rounding function that might do what you want. 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]
]
--Gregg
[3/7] from: chris:ross-gill at: 29-May-2002 14:58
Hi Mat,
> >> print to-integer 1.6
> 1
I don't know of one, but here's my own:
round: func [
dec [integer! decimal!]
/local int
][
if 0.5 <= (dec - int: to-integer dec) [int: int + 1]
int
]
- Chris
[4/7] from: chris:langreiter at: 29-May-2002 21:02
> Is there such a beast or must one write a function to do it?
round: func [x] [to-integer .5 + x]
Enjoy ;-)
[5/7] from: mat:0wnerage at: 30-May-2002 8:43
Hi Christian,
>> Is there such a beast or must one write a function to do it?
Christian> round: func [x] [to-integer .5 + x]
Haha, yes. :) Could not see the wood for the trees. I should show you
my version for comedy, I was using string manipulation to get the
digits after the decimal. <blush>
Regards,
Mat.
[6/7] from: rpgwriter:y:ahoo at: 30-May-2002 18:50
--- Mat Bettinson <[mat--0wnerage--com]> wrote:
> Folks,
> >> print to-integer 1.6
<<quoted lines omitted: 6>>
> Is there such a beast or must one write a function
> to do it?
I don't think there is one, but it shouldn't be too
ugly. Rounding fractions >=0.5 away from 0, do this:
round-off: func [ x [number!] ] [
return either greater? x 0 [
to-integer x + 0.5
] [
to-integer x - 0.5
]
]
[7/7] from: rpgwriter::yahoo::com at: 30-May-2002 18:52
--- Christian Langreiter <[chris--langreiter--com]> wrote:
> > Is there such a beast or must one write a function
> to do it?
>
> round: func [x] [to-integer .5 + x]
This has results which are probably undesired with
negative inputs.
Chris Dicely
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted
Librarian comment
the round function is supplied as standard in REBOL 1.3 and later.