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

-- 
To unsubscribe from this list, please send an email to
[EMAIL PROTECTED] with "unsubscribe" in the 
subject, without the quotes.

Reply via email to