Archived

This topic is now archived and is closed to further replies.

Vlion

Random number between 2 bounds.

Recommended Posts

Hey. I''ve found myself needing to get a number between 2 bounds, IE 0 and 1, or 0 and 255. I know I can do a integer result with rand() and the modulus operator, but I`d really like a floating point solution. What`s worked for you guys ? From what I`ve seen of perlin noise its really slow. Other random formulae I really don`t know of. :-/ I can`t recall ever running across this problem in my various studies. Oh yeah- ideally its prety fast- its going to be for a particle emitter. Thanks, ~V''lion Bugle4d

Share this post


Link to post
Share on other sites
#define RANDOM_FLOAT (rand()/RAND_MAX)
#define RandomNumber(a) (RANDOM_FLOAT*a)
#define RandomRange(a,b) (RandomNumber(b-a)+a)



RANDOM_FLOAT will give you a random number between 0 and 1, RandomNumber will give you a random floating point between 0 and a, and RandomRange will give you a random number between a and b.

Hope this helps!





"There are only three types of people in this world: those who can count, and those who can't."

Just3D
Justin Nordin
J Squared Productions
www.jsquaredproductions.com

[edited by - Just3D on July 27, 2002 6:19:49 PM]

[edited by - Just3D on July 27, 2002 6:20:41 PM]

[edited by - Just3D on July 27, 2002 6:22:08 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Just3d,

Those macros should probably read as follows:

#define RANDOM_FLOAT ((float)rand()/(float)RAND_MAX)
#define RandomNumber(a) (RANDOM_FLOAT*a)

Share this post


Link to post
Share on other sites
What if you want to find a random # that is not completely random? for instance, what if you want the lower #s to occur more often. In essence, how can you generate a random #, n, where the frequency of the a number = 1 / number ^ 2 or somethign similar... is there a way to do this using a funcion for the frequency f(n)?

thanx for the help!

tazzel3d ~ dwiel

Share this post


Link to post
Share on other sites
quote:
Original post by cedricl
Well, if you square the random number before dividing by RAND_MAX², there should be more small numbers than large numbers.

Warning - RAND_MAX squared might roll-over on some implementations. Might want to do the division first and square the result.



[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions | Organising code files ]

Share this post


Link to post
Share on other sites
why didn't I think of it to start with!?!?!?! all you hav to do to generate biased random numbers is create a function to pass the random number through... example:


    

#define RANDOM_FLOAT ((float)rand()/(float)RAND_MAX)

// biases a random # between 0 and 1

float BiasNumber(float num)
{
return num * num;
}

// scales the biased # between the range of min and max

float ScaleNumber(float num, float min, float max)
{
return min + (max - min) * num;
}

// to generate the number, execute:

float min = 0;
float max = 1000;
float randomnum = ScaleNumber(BiasNumber(RANDOM_FLOAT, min, max);



of course this could all be put into one function, but for ease of explantaion, I wrote it as two. In this way, you can bias the number any way you wish as long as the number always stays between the range of 0 and 1.

if anyone else can come up with a way to bias the number or can pick my method apart, please do so!

Tazzel3d ~ dwiel

[edited by - tazzel3d on July 27, 2002 10:27:30 PM]

Share this post


Link to post
Share on other sites
if you need biased numbers you should look into bell curves and statistics.

the most efficent way if your range is small could be to use a lookup table with the correct distribution. just squaring the numbers may seem like a good idea, lets see.

normal random distribution of 0-9
0 1 2 3 4 5 6 7 8 9

distribution squared
0 1 4 9 16 25 36 49 64 81

distribution normalized (ie num/maxNum*range)
0 0.111 0.444 1 1.778 2.778 4 5.444 7.111 9

hmm, seems the distribution just got spread away from the center (ie clustered below and above the mean).

ie that wont work.

Share this post


Link to post
Share on other sites
a person,
if you dont start with 0-9 and instead with 0-1, i believe, squring it will work....



rand .0 .1 .2 .3 .4 .5 .6 .7 .8 .9
bias .0 .01 .04 .09 .16 .25 .36 .49 .64 .81



hmm.... guess not...

wait.. would this not work?

seems to me that now instead of the mean bieng 0.45 in the caes of the top 10 #s, it is now 0.285, and now all biased#s that started below .707.... are now rounded down

please explain y this method doesnt work...

lol
ive changed my mind on weather this method works or not around 4 times durring the time of this post...

someone has probobly already cleared the whole thing up
*sigh*

tazzel3d ~ dwiel

Share this post


Link to post
Share on other sites
quote:
Original post by a person
if you need biased numbers you should look into bell curves and statistics.

the most efficent way if your range is small could be to use a lookup table with the correct distribution. just squaring the numbers may seem like a good idea, lets see.

normal random distribution of 0-9
0 1 2 3 4 5 6 7 8 9

distribution squared
0 1 4 9 16 25 36 49 64 81

distribution normalized (ie num/maxNum*range)
0 0.111 0.444 1 1.778 2.778 4 5.444 7.111 9

hmm, seems the distribution just got spread away from the center (ie clustered below and above the mean).

ie that wont work.

Huh? Care to explain how you can say that this distribution is "clustered below and above the mean"? The first derivative of this function keeps increasing (obviously), so it''s only "clustered" below the mean. The gap between two numbers is 2n, so it grows increasingly sparse.

Cédric

Share this post


Link to post
Share on other sites
If I''m reading this right, I believe your mean will increase exponentially with the range you input which I don''t think you want. Hmm.. I may have to leave for a while to think of a solution here....

_____________________________

And the Phoenix shall rise from the ashes...

--Thunder_Hawk -- ¦þ
______________________________

Share this post


Link to post
Share on other sites
Ahah !
Late nite genius strikes again.

CRandom::CRandom()
{
stored = 0;
}
void CRandom::GetRandom()
{
if(!stored)
{
srand((unsigned)(time(NULL)));
}
stored = rand();
}

float CRandom::GetNumInRange(float upper, float lower)
{
float retval;

float diff = upper-lower;

GetRandom();

retval = fabs(diff*sin(stored));

return retval;
}


okay, why sin() ?
It returns between 1 and -1.
I abs it, and its between 1 and 0.
Seed it with rand(), multiply it times the difference, kaboom; a slow, more-or-less-random tween bounds solution.

Bugle4d

Share this post


Link to post
Share on other sites
So now im kinda wondering how you would find the % of #s based on the bias function, f(x) = x*x, and how to graph the bias somehow so I could see the frequency of each #. This would be a good way to test the bias function to see if it correctly biases your #s

Tazzel3d ~ dwiel

P.S. I prolly just made no sence what so ever, but please bear with me.. lol
all I want to do is graphically represent the amount of bias an equation gives.

thanx

Share this post


Link to post
Share on other sites
Like I said, the first derivative gives you a pretty good idea; the lower it is, the more numbers there is around that point.

So
f(x) = x²
f''(x) = 2x

That''s a linear graph, so there are more numbers close to 0² than there are close to 100². It also works for

f(x) = x

There is probably a more correct mathematical way of representing the ''density'' of a function, but I don''t know. Maybe with integrals...

Cédric

Share this post


Link to post
Share on other sites
I guess you might be able to just graph the function.. or its inverse it you wanted to see the ''density'' function. Will this work acuratly? If so, it makes it much easier to generate the bias function...

just an idea

Tazzel3d ~ dwiel

Share this post


Link to post
Share on other sites
float randomnum = ScaleNumber(BiasNumber(RANDOM_FLOAT, min, max);

- Tazzel3d

there a " missing here? BiasNumber takes 1 value no?
Dont speak C, so forgive me if im wrong.

and what is RAND_MAX?
surely you just want a random number between 0 and 1, if you divide it by anything you risk affecting the squaring thing, cause you squash the data.

if you take your random float (0 to 1), square it, times it by the range (max-min), and add on min, then thats what you want.

note if your range is large, eg. 100,000 then you'll have 5 0's at the end of your number.

anyway, i've knocked up a quick program in Blitz, and it demonstrates the squaring thing to work lovely, its not much, but it does seem to show that the ditribution is shaped like the inverse tho.

fatray

    
;bias random number generator.
Graphics 640,480,16,2

Const Number_of_numbers=50000

Dim number#(Number_of_numbers)
;an array of number_of_numbers +1 floats,
;(0-n_o_n inclusive), # is blitz for float
Dim frequency(500)
; an array of 500 integers, used for drawing my bar chart

For a=1 To Number_of_numbers
;each number = random float between 0 and 1
number(a) = Rnd#(0,1)
Next

bar_chart_calc()
render()
WaitKey()

For a=1 To Number_of_numbers
;square each number, to hopefully bias the
;numbers towards the origin
number(a) = number(a) * number(a)
Next

bar_chart_calc()
render()
WaitKey()
End

Function bar_chart_calc()
;we'll be drawing a bar chart with frequency along the Y, so we need to count what interval the number lies in.
;we'll have the intervals 0.002 wide, (range/500)

class_width#=0.002
For a=0 To 500
frequency(a)=0
Next

For a=1 To Number_of_numbers
;class is an int
;just need to scale up the range by 500
class=number(a)*500
frequency(class)=frequency(class)+1
Next
End Function

Function render()
Cls
Color 200,0,0
For a= 0 To 500
Line a+70,400,a+70,400-frequency(a)*1
Next
Color 200,200,200
Text 320,460,"Any key to cont.",1,1
End Function


Edit: put in the blitz code.
edit: then tidied it up a bit, and threw in more coments for any non-blitzers


[edited by - fatray on August 2, 2002 7:34:04 PM]

[edited by - fatray on August 2, 2002 7:35:00 PM]

[edited by - fatray on August 2, 2002 7:41:14 PM]

Share this post


Link to post
Share on other sites