Sign in to follow this  

Truly random numbers

This topic is 4378 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I need some random numbers. Right now, I'm using this code:
srand( time(NULL) );
float r = (int) filenames.size() * (rand() / ((float)RAND_MAX+1.0f));

fname = dirname + "\\" + filenames[(int)r];
And, because the number of elements in the array doesn't change, and because I'm casting to an int, I keep getting 4. (I always seem to be converting to a float to get it within a range, and then casting to an int) This is really beginning to annoy me. It seems like I can never get truly random numbers using the rand function. Does anyone know of a method, or any other functions that don't include writing 100 lines of ridiculouly math-intensive code?

Share this post


Link to post
Share on other sites
Perhaps your clock stopped ticking ? So time (NULL) = constant [grin].

Seriously, what is the value of filenames.size () ?. From what I saw, the value of filenames.size () maybe too small (around 3 or 4) so multiplying it by [0, 1) then casting back to int won't seem to change the value (if you keep it as float you'll see the changes).
You may try this little program with srand (), then mutate the 1024 value to higher or lower, you'll see what I mean:


#include "time.h"
#include "stdio.h"
#include "string.h"

int main ()
{
srand( time (NULL)) ;

//If we change 1024 by 100 or 10, there'll be a very little chance the return value will be changed
float r = 1024 * rand() / ((float)RAND_MAX+1.0f) ;
char p[64] ;
sprintf (p, "%u", static_cast<int> (r)) ;

cout << p ;

return 0 ;
}




You may want to multiply filenames.size () by 100 to have more significant sparse random-ed value.
Good luck.

Share this post


Link to post
Share on other sites
Quote:
Original post by Endar
Right now, I'm using this code:
srand( time(NULL) );
float r = (int) filenames.size() * (rand() / ((float)RAND_MAX+1.0f));

You're not calling srand every time are you? You should only seed the random number generator once. Otherwise it's likely your code is executing faster than the resolution of the timer, so each call to srand seeds the random number generator at exactly the same point thus giving you the same "random" number repeatedly.

Also, float r = (int) filenames.size() * (rand() / ((float)RAND_MAX+1.0f)); can probably be replaced by int r = (filenames.size() * rand()) / (RAND_MAX + 1);, which avoids the floating-point conversions. The only thing to watch out for here is that filenames.size() * RAND_MAX <= std::numeric_limits< int >::max().

Enigma

Share this post


Link to post
Share on other sites
Guest Anonymous Poster

srand( time(NULL) );

// if RAND_MAX<filenames.size() you get an even but digital spread
unsigned int ui = ( filenames.size()*rand() )/RAND_MAX;

// if RAND_MAX<filenames.size() you get the first RAND_MAX files
unsigned int ui = rand()%filenames.size();

// this would go bang if filenames.size() is empty
fname = dirname + "\\" + filenames[ ui ];


Share this post


Link to post
Share on other sites
Stein: I tried yours, and it's working well. Thanks!

Engima: No, the srand and rand are only called once each.

Hopefully, once I get the rest working, this should go well. If not, you'll be hearing from me in this thread again.

Thanks guys!

Share this post


Link to post
Share on other sites
Quote:
Original post by stein
How about this?
int r = rand()%filenames.size();
:)


Be aware that rand() has very poor randomness in its less significant bits, and operator% uses only those bits, so don't expect particularly random results.

In fact, if you only call srand() and rand() once, you're better off using
int r = time() / filenames.size();

since that requires far fewer multiplication and division operations and is just as "random."

--smw

Share this post


Link to post
Share on other sites
On the original topic title looking for truly random numbers, they may not exist. See the classic arguments about nondeterminism in the Universe.

The built-in rand function is easily predictable and may generate obvious cyclic patterns when used with operator%, depending on your seed and denominator.

Although your snippet doesn't need it, if your game uses other random numbers you might consider the boost random number generators.


boost::random:: {pick your type of generator} < ... > Generator;
...
Generator.seed( time(NULL) );
...
MyRandomNumber = Generator();



frob.

Share this post


Link to post
Share on other sites

This topic is 4378 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this