View Single Post
Old 22nd September 2019, 10:01   #3  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
HH, 'myInt' is not defined as an optional arg to your function, but you use 'Default(myInt, 2)'.

Here differing rounding stuff:- https://forum.doom9.org/showthread.p...84#post1814184

Quote:
Originally Posted by StainlessS View Post
Round value down to next lower multiple of factor ALWAYS
(value-1)/factor*factor

To round up, to the next higher multiple of factor, when value is not an exact multiple of factor.
(value+factor-1)/factor*factor.

To round up, to the next higher multiple of factor, ALWAYS.
(value+factor)/factor*factor

To round to nearest multiple of factor.
(value+factor/2)/factor*factor, OR better yet, (value*2+factor)/(2*factor)*factor. (marginally less prone to intermediate result precision loss)
Where above value and factor are both type int. [above method 2 and 4 most often used, 1 and 3 rarely]

I seem to have missed out round down, [think it was already discussed, and so I missed it out]
value/factor*factor.

EDIT:
Code:
Function RoundInt(int value, int "factor", int "roundMode") { # https://forum.doom9.org/showthread.php?p=1885480#post1885480
    # Round +ve Int Value to a multiple of +ve Int Factor, using rounding mode RoundMode. Result will not go -ve.
    factor = Default(factor,2)              # Default round to multiple of 2, even
    roundMode=Default(roundMode,0)          # 0=Down(Default), 1=Nearest, 2=Up, 3=ALWAYS_DOWN, 4=ALWAYS_UP
    Assert(0 <= value,String(value,"RoundInt: 0 <= value(%.0f) [result undefined for -ve value]"))
    Assert(0  < factor,String(factor,"RoundInt: 0 < factor(%.0f)"))
    Assert(0 <= RoundMode <= 4,String(RoundMode,"RoundInt: 0 <= RoundMode(%.0f) <= 4 "))
    return
        \   (RoundMode==0)  ?   value / factor * factor              [* Down                   *]
        \ : (RoundMode==1)  ?   (value*2+factor)/(2*factor)*factor   [* Nearest : About same as (value+factor/2)/factor*factor but without intermediate result precision loss *]
        \ : (RoundMode==2)  ?   (value+factor-1)/factor*factor       [* Up                     *]
        \ : (RoundMode==3)  ?   (value-1)/factor*factor              [* ALWAYS_DOWN : Rare Use : Result always less than Value, except where Value=0 *]
        \ :                     (value+factor)/factor*factor         [* ALWAYS_UP   : Rare Use : Result always greater than Value *]
}

FACTOR = 4  # round to multiples of 4

SSS= "Val Down Near   Up ADwn  AUp\n"
For(i=0,16) {
    S=""
    for(roundMode=0,4) {
        r = RoundInt(i, FACTOR, roundMode)
        S = S + String(r,"%5.0f")
    }
    SSS = SSS + String(i,"%2.0f]") + S + "\n"
}

BlankClip(Width=320,height=360)
Subtitle(SSS,Font="Courier New",lsp=0)    # Courier New = MonoSpaced font


EDIT:
Code:
 \ : (RoundMode==1)  ?   (value*2+factor)/(2*factor)*factor   [* Nearest : About same as (value+factor/2)/factor*factor but without intermediate result precision loss *]
where above factor/2 is eg 3/2, then we lose precision due to half of 3 being 1, instead of 1.5 [which we cannot have in type int], chosen method avoids that precision loss at that stage.
Where factor is KNOWN even [EDIT: KNOWN power of 2, including 1] (most cases) then could use the simpler method.

EDIT: Result will not go -ve for any round operation. Value Must be +ve, Factor must be 1 or greater.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 23rd September 2019 at 10:48.
StainlessS is offline   Reply With Quote