Rounding random numbers to the nearest hundredth?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
keyspinner
Prole
Posts: 24
Joined: Mon Sep 01, 2008 12:03 am

Rounding random numbers to the nearest hundredth?

Post by keyspinner »

How can I round random numbers to the nearest hundredth?
Also, I'm making a "stock market" demo and I want the stocks to randomize + at most $5 or - at most $5 every 3 seconds.
so I would have

stock1 = 50 3 seconds stock1 = 53.45
or something.

Please help me with changes I need to make the above possible.

My current code
(Yes I know my math.random thing is not correct I just put it in there to test.)

Code: Select all

function load()
love.graphics.setFont(love.graphics.newFont(love.default_font, 12))
stock1 = 50
stock2 = 50
stock3 = 50
end

function update(dt)
stock1 = stock1 + (dt * (math.random (-100,100))) - (dt * (math.random (-100,100)))
stock2 = stock2 + (dt * (math.random (-100,100))) - (dt * (math.random (-100,100)))
stock3 = stock3 + (dt * (math.random (-100,100))) - (dt * (math.random (-100,100)))
end

function draw()
love.graphics.draw(stock1, 50, 50)
love.graphics.draw(stock2, 50, 100)
love.graphics.draw(stock3, 50, 150)
end

emonk
Prole
Posts: 24
Joined: Tue Aug 12, 2008 11:43 am

Re: Rounding random numbers to the nearest hundredth?

Post by emonk »

keyspinner wrote:How can I round random numbers to the nearest hundredth?
Lua's math library doesn't have a 'round to n places' function, but you can use the math.floor() library function and some simple math to do something similar:

Code: Select all

local rounded = math.floor(unrounded * 100 + 0.5) / 100;
You can use that to add a generalized 'round to n places' function this way:

Code: Select all

-- return 'v' rounded to 'p' decimal places:
function round(v, p)
local mult = math.pow(10, p or 0) -- round to 0 places when p not supplied
    return math.floor(v * mult + 0.5) / mult;
end;
Of course you could just do all the calculations to the limits of the floating point accuracy and just round on output using the string.format() library function:

Code: Select all

local v = 2/3;
print(string.format("%.2f", v);
--^ prints "1.67" to stdout
print(string.format("%.2f", v * 100);
--^ prints "166.67" to stdout
Sarcasm - just one of the services I offer.
User avatar
keyspinner
Prole
Posts: 24
Joined: Mon Sep 01, 2008 12:03 am

Re: Rounding random numbers to the nearest hundredth?

Post by keyspinner »

I'm gonna need some more explaining but I think I know what you are trying to say.
emonk
Prole
Posts: 24
Joined: Tue Aug 12, 2008 11:43 am

Re: Rounding random numbers to the nearest hundredth?

Post by emonk »

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 :x 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;
Sarcasm - just one of the services I offer.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 13 guests