keyspinner wrote:I'm gonna need some more explaining but I think I know what you are trying to say.
Will go a bit more in-depth and fix some basic assumption errors in the above code at the same time
<LECTURE>
Lua's standard
math library includes two functions for rounding:
math.floor(x) and
math.ceil(x). Both of them return an integer value that is not larger than (for floor) or not smaller than (for ceil) the supplied floating point number. From the docs:
Lua 5.1 Reference Manual wrote:
math.ceil(x)
Returns the smallest integer larger than or equal to x.
math.floor(x)
Returns the largest integer smaller than or equal to x.
So
floor(1.6) returns 1, and
ceil(1.1) returns 2. Unfortunately (as I keep forgetting),
floor(-1.6) returns -2 and
ceil(-1.1) returns 1
so we need to account for negative numbers.
Now, since we don't have a built-in function for rounding to a number of decimal places (2 decimal places for nearest hundredth, etc), we have to rely on the integer functions and a bit of math. If you want to round to two decimals you need to multiply by 100, convert to integer, then divide by 100 to get your result. Because math.floor() will truncate 1.999999 to 1 instead of rounding up, we need to add 0.5 to the multiplied value to correct the rounding.
Since having a general function is much more useful than a number of
RoundTo100th(n) type functions, we can calculate the multiplier/divider (let's call it scale for now) by using the
math.pow() function to get the
pth power of 10. For one decimal place we call
math.pow(10, 1) which returns 10, for two places it's
math.pow(10,2) returning 100 and so on.
Putting that all together, and adding proper handling for negative numbers (using
math.abs())
Code: Select all
-- Round 'v' to 'p' decimal places
function Round(v, p)
-- figure out scaling factor for number of decimal points, or 0 if 'p' not supplied
local scale = math.pow(10, p or 0);
-- calculate result ignoring sign
local res = math.floor(math.abs(v) * scale + 0.5) / scale;
-- if 'v' was negative return value should be too
if v < 0 then
res = -res;
end;
-- return rounded value
return res;
end;
So now we can call Round(-2.2) and get -2 as a result (missing param 'p' is converted to 0, math.exp(10,0) == 1). Or we can call Round(2/3,3) and get 1.667.
</LECTURE>
Does that help?
For obfuscation nuts only:
Code: Select all
function round(a,b) return a*math.floor(math.abs(a)/math.pow(10,b or 0)+0.5)/math.abs(a)/math.pow(10,b or 0); end;
-- or worse:
function rnd(a,b)local _f,_a,_p=math.floor,math.abs,math.pow;return a*_f(_a(a)/_p(10,b or 0)+0.5)/_a(a)/_p(10,b or 0); end;