Skip to main content
GameDev.net gamedev.net
🔒 Locked

Random Number Generation Issue

Started by Vices Dec 19, 2006 at 8:54 AM 14 replies 1.7k views
Original Post
Vices
Vices
Hi, for some reason my random number isn't changing from one cycle to the next.

void aver(){
	
	for (int x = 0; x < 10; x++){
		srand(time(0));
		number = (rand()%100);
		cout << "Random Number " << number << endl;
		cout << "Ticker " << ticker << endl;
		cout << "Total " << total << endl;
	
		if(number != 3 || number != 52 || number != 80) {
		ticker ++;
		}
		else{
			total = ticker;
			ticker = 0;
		}
	

stevenmarky
stevenmarky
Quote:
time_t time ( time_t * timer );

Get current time.
Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock.

I think 10 iterations will take a lot less than 1 second - so your seed value is constant. You only need to seed once.
rip-off
rip-off
Put srand() before the for loop.

srand seeds the random number generator. After a call to srand the generator always generates the same sequence of values. We use time() as a seed as it changes every time the program is run.

However, your code calls time 10 times in a loop. The loop executes in less than one second. So time(NULL) returns the same value.

As a general rule, call srand once near the start of your program.
kadaf
kadaf
It's because you for each cycle resets the random seed with srand() to the same value. Your loop is so fast that time() won't change before you've finished looping.

Simply call srand() outside the loop instead.

By the way, it's usually not a good idea to use rand()%SOMETHING, because that will return the low bits of your random number - and those are usually "less random" than the high bits.

EDIT: somebody beat me to it :)
-- Rasmus Neckelmann
Vices
Vices
Is there any way to generate a random number faster, to optimize the loop time?

What are ticks and how many of those are there a second? Is it possible to use something that occurs faster than a second?

slymr
slymr
Quote:
Original post by Vices
Is there any way to generate a random number faster, to optimize the loop time?

What are ticks and how many of those are there a second? Is it possible to use something that occurs faster than a second?


There are large amounts of ticks a second and you don't need something faster than a second. All you need to do is seed the program ONCE. If you seed again ( with the same value ), then it just generates the same numbers.
slymrHopefully game is in progress.
Vices
Vices
Okay, wow. Putting the srand outside of the loop made it work fine, thank you al so much!

Could somene explain the high bits and low bits part of the random function? ANd how to use the high bits?

stevenmarky
stevenmarky
You're welcome :)

I don't know what you mean by high and low bits part of the rand function.
SimonForsman
SimonForsman
Quote:
Original post by kadaf
It's because you for each cycle resets the random seed with srand() to the same value. Your loop is so fast that time() won't change before you've finished looping.

Simply call srand() outside the loop instead.

By the way, it's usually not a good idea to use rand()%SOMETHING, because that will return the low bits of your random number - and those are usually "less random" than the high bits.

EDIT: somebody beat me to it :)


The problem is the max value of rand();

it returns a value between 0 and RAND_MAX

for simplicity we could pretend that RAND_MAX is 19 (it is generally alot higher)

then rand()%15 would be 0 if rand() returns 0, 1 if it returns 1, etc until 15, then for 15-19 its 0-4 again, thus its twice as likely to result in for example 2 than it is to result in 8. (not what you want really).

a better approach is generally to do (double)rand() / (double)RAND_MAX; to get a value between 0.0 and 1.0 and then multiply with your range.

thus instead of:
int value = rand()%100;

you do:
int value = 100.0*(double)rand() / (double)RAND_MAX;

the modulus operator works pretty well with short ranges, but the closer your range is to RAND_MAX the more likely it is that you'll get low numbers.
rand()%x will only work perfectly if (RAND_MAX+1)%x == 0; (since RAND_MAX is usually the highest value you can can store in a 16 or 32 bit unsigned integer (RAND_MAX+1)%x should be 0 if x is a power of 2. (2,4,8,16,32,etc)

on a 16bit platform (MS-DOS for example) RAND_MAX is usually 65535 ,
thus rand()%100 will give 36-99 for 655 different values from rand() each, and 0-35 for 656 different values. thus 0-35 will occur more often than they should

rand()%10000 on the other hand would get 0-5535 for 6 different values each and 5536-9999 for 5 different values each. (the chance of getting for example 1000 would be 20% greater than getting 6000) (a significant difference)

sorry for the long post.
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
RavynousHunter
RavynousHunter
Seeding outside of the random loop doesn't seem like it would fix the problem, as you would have the same seed throughout the loop, unless I'm missing something. What I usually do is seed inside the loop, seeding the generator with a random number between say, 1 and 50, for each iteration.

Something like this:
while (condition==true){    srand((rand() % 49)+1); //seed the generator w/ a number between 1 and 50 inclusive    value = (rand() % 19) + 1; //if your rolling a d20, for example}
rip-off
rip-off
Quote:
Original post by RavynousHunter
Seeding outside of the random loop doesn't seem like it would fix the problem, as you would have the same seed throughout the loop, unless I'm missing something. What I usually do is seed inside the loop, seeding the generator with a random number between say, 1 and 50, for each iteration.

Something like this:
*** Source Snippet Removed ***


...

So, you seed the generator, with a number that is generated by the generator...

Have you even tested your code?
Gooberius
Gooberius
You only need to call srand once, after than calling rand will automatically reseed the RNG.
JohnBolton
JohnBolton
Quote:
Original post by RavynousHunter
Seeding outside of the random loop doesn't seem like it would fix the problem, as you would have the same seed throughout the loop, unless I'm missing something.

You are missing something. rand() returns a random sequence of numbers. srand() computes the first value in that sequence, You only need to call it once.
Quote:
Original post by RavynousHunter
What I usually do is seed inside the loop, seeding the generator with a random number between say, 1 and 50, for each iteration.

The parameter to srand() is not (and should not) be restricted to a particular range of values. The result is that rand() will return the same sequence more often. While it is possible to call srand() with rand() as a parameter every time, the result will be less random than just calling srand() once.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
rip-off
rip-off
Quote:
Original post by JohnBolton
While it is possible to call srand() with rand() as a parameter every time, the result will be less random than just calling srand() once.


I think it will end up with the exact same sequence every time.

For example, this code
int main(){    for( int i = 0 ; i < 50 ; ++i )    {        for( int j = 0 ; j < 20 ; ++j )        {            srand((rand() % 49)+1);             int value = (rand() % 19) + 1;            std::cout << value << ' ';        }        std::cout << std::endl;    }}


Prints:
5 12 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 2 9 13 10 15 

Every time its run.
chowe6685
chowe6685
To reiterate since there is a lot of misinformation floating around

you call srand() ONCE at the beginning of your program

you call rand() every time you want a random number

Using srand() multiple times is almost always asking for trouble unless you know EXACTLY what you are doing
Chad Smith
Chad Smith
Quote:
Original post by SimonForsman
Quote:
Original post by kadaf
It's because you for each cycle resets the random seed with srand() to the same value. Your loop is so fast that time() won't change before you've finished looping.

Simply call srand() outside the loop instead.

By the way, it's usually not a good idea to use rand()%SOMETHING, because that will return the low bits of your random number - and those are usually "less random" than the high bits.

EDIT: somebody beat me to it :)


The problem is the max value of rand();

it returns a value between 0 and RAND_MAX

for simplicity we could pretend that RAND_MAX is 19 (it is generally alot higher)

then rand()%15 would be 0 if rand() returns 0, 1 if it returns 1, etc until 15, then for 15-19 its 0-4 again, thus its twice as likely to result in for example 2 than it is to result in 8. (not what you want really).

a better approach is generally to do (double)rand() / (double)RAND_MAX; to get a value between 0.0 and 1.0 and then multiply with your range.

thus instead of:
int value = rand()%100;

you do:
int value = 100.0*(double)rand() / (double)RAND_MAX;

the modulus operator works pretty well with short ranges, but the closer your range is to RAND_MAX the more likely it is that you'll get low numbers.
rand()%x will only work perfectly if (RAND_MAX+1)%x == 0; (since RAND_MAX is usually the highest value you can can store in a 16 or 32 bit unsigned integer (RAND_MAX+1)%x should be 0 if x is a power of 2. (2,4,8,16,32,etc)

on a 16bit platform (MS-DOS for example) RAND_MAX is usually 65535 ,
thus rand()%100 will give 36-99 for 655 different values from rand() each, and 0-35 for 656 different values. thus 0-35 will occur more often than they should

rand()%10000 on the other hand would get 0-5535 for 6 different values each and 5536-9999 for 5 different values each. (the chance of getting for example 1000 would be 20% greater than getting 6000) (a significant difference)

sorry for the long post.


A little off topic but I actually just rated you up for that post. I have herd that before, but I never really did understand it, and you actually just made me understand it a lot more. Thanks a lot man! :).

Chad



Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.