random number is always 1

I've been working on this game that requires a random number between 0 and 6. Here's the code I used:

1
2
srand(static_cast<unsigned int> (time(0)));
pos = rand() % 7;


This random function was working fine for a while, but then I noticed it started returning 1 every time. At first I thought it was just a coincidence, but it kept happening. Over and over again it returned 1, dozens of times. Finally I tried changing the code to this:

1
2
3
4
5
srand(static_cast<unsigned int> (time(0)));
do 
{
	pos = rand() % 10;
} while (pos > 6);


Now it works fine. But I hate doing it this way, and I don't understand why my original code didn't work the way it was supposed to. Any ideas?

I don't know if it matters, but I'm using Xcode v3 on OSX 10.6.

Thanks.
How about that kiss, Explodey?
If you don't get the joke, never mind. It's from an old cartoon.

Well your original code should work fine, assuming that you seed the PRNG (pseudo-random number generator) one time only, preferably in main().

1
2
3
4
5
6
7
8
9
10
11
void my_func()
{
    int pos = rand() % 7;
}

int main()
{
    srand(static_cast<unsigned int> (time(0)));

    my_func();
}


Please post the rest of the code, there may be a bug hiding somewhere.
You're not calling srand for each random number, are you? You should only be calling it once at the start of the program.

srand = call once
rand = call every time you need a new random number.
No, I'm not calling srand for each random number. I just included it in my example code because I thought it might be relevant.

Okay, why don't I just show you main(). If I included all the functions and the struct, it would be pages and pages of text, and I doubt you're going to want to read all of that.

Oh and by the way, Catfish666, I've been posting as Explodey on forums for years, and you're the first person to get the reference. Kudos to you!

Here's the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
int main(int argc, char* args[])
{
	short int form, pos, fCode;
	short int sNum = 0;
	bool noOver;
	
	srand(static_cast<unsigned int> (time(0)));
	
    //Initialize
    if (init() == false)
    {
        return 1;
    }
	
    //Load the files
    if (load_files() == false)
    {
        return 1;
    }
	
	pos = rand() % 7;
	form = rand() % 5;
	
	ScaleForm sf(pos, form);
	
	apply_surface( 0, 0, background, screen );
	apply_surface(-20, 150, neck, screen);
	apply_surface(0, 400, pressAny, screen);
	sf.ShowMarkers();
	SDL_Flip(screen);
	
	while (true)
	{
		if ((SDL_PollEvent(&event)) && (event.type == SDL_KEYDOWN))
		{
			break;
		}
	}
	
	while (!(sf.AreAllFull()))
    {
		fCode = sf.GetRndNext();
		if (fCode == -1)
		{
			break;
		}

		getInput(sf, sNum, fCode);
		
		noOver = sf.UpdateUsr(sNum, fCode);
		if (!noOver)
		{
			break;
		}
	}
	
	if (sf.IsCorrect())
	{
		winner(sf);
	}
	else 
	{
		if (noOver)
		{
			swapAnswers(sf);
		}
		else 
		{
			loserOvf(sf);
		}
	}

    //Clean up
    clean_up();
	
    return 0;
}
Well in your main(), the only place you use pos is at line 24:

23
24
25
	
	ScaleForm sf(pos, form);
	


You should be getting a "correct" value from 0 to 6.
So something is messed up in the ScaleForm constructor, probably.

By the way, a minor observation: std::rand() returns int and not short int.
Are you not getting conversion warnings from the compiler?
Last edited on
Well, here's the constructor, and the only line of code that uses that passed value:

1
2
3
4
5
ScaleForm::ScaleForm(short int posit, short int frm)
{
	m_Position = posit;
	// etc etc....
}


It seems to me that if there were a problem with my constructor, then changing my code to this wouldn't help:

1
2
3
4
5
6
7
8
do 
{
	pos = rand() % 10;
} while (pos > 6);

form = rand() % 5;

ScaleForm sf(pos, form);


But it does help -- it totally fixes the problem, and I don't understand why. This totally baffles me!

And I didn't realize that std::rand() has to return an int. My entire knowledge of c++ comes from two books I bought last year, plus some helpful tips I've gotten on forums from folks like yourself. But anyway, no compiler warnings, and I just tried changing those two variables to int types, but it still seems to run the same.
Explodey wrote:
And I didn't realize that std::rand() has to return an int.

You are not expected to learn all these things by heart, just keep a reference at hand:

http://www.cplusplus.com/reference/
http://www.cplusplus.com/reference/cstdlib/rand/

Alternative Wiki-style reference, downloadable:
http://en.cppreference.com/w/
http://en.cppreference.com/w/cpp/numeric/random/rand

As for your code, I do not see where the bug is.
Did you try printing the values of pos and m_Position?

1
2
3
4
5
6
7
8
9
ScaleForm::ScaleForm(short int posit, short int frm)
{
	clog << posit;

	m_Position = posit;
	// etc etc....

	clog << m_Position;
}


By the way, another minor tip: with time you should unlearn using namespace std;.
Avoid it especially in header files.

http://www.parashift.com/c++-faq/using-namespace-std.html
Last edited on
When you call rand multiple times it's supposed to return a sequence of numbers that appear to be random.

When you call srand with different seeds you will get different sequences from rand, but that doesn't mean that the sequences will be totally random if you compare them.

Also note that the time function returns the time in seconds so if you run your program more than once in the same second you are guaranteed to get the same sequence of numbers from rand.
Last edited on
Okay, I tried printing my values, and I did discover that pos is actually 0 every time, not 1.. oops. But I was still getting the same number for pos every time. Then I tried adding this code to the part where I'm generating the two random numbers:

1
2
3
4
5
6
7
8
	for (int i = 0; i < 20; i++)
	{
		pos = rand() % 7;
		form = rand() % 5;
		
		cout << "pos = " << pos << "\t";
		cout << "form = " << form << endl;
	}


Here's what I got:

pos = 0 form = 4
pos = 4 form = 0
pos = 1 form = 0
pos = 3 form = 4
pos = 6 form = 1
pos = 3 form = 2
pos = 0 form = 2
pos = 4 form = 2
pos = 0 form = 0
pos = 3 form = 3
pos = 0 form = 1
pos = 6 form = 3
pos = 3 form = 2
pos = 5 form = 3
pos = 0 form = 3
pos = 4 form = 4
pos = 4 form = 3
pos = 2 form = 2
pos = 3 form = 1
pos = 6 form = 1

Seems pretty random, right? But then I ran it again several times, and every time, the first value for pos was always 0. Like, at least a dozen times. But this only happens with pos, not with form. It seems that any time I use rand()%7, the first number I get is always 0. It doesn't happen with rand()%5 or any other random number generator as far as I can tell.

So any time I need a number between 0 and 6, I guess I'll have to call rand() twice and use the second value. But I shouldn't have to do this, right?

And btw, I'm definitely not running my program more than once in the same second.

UPDATE: I just tried changing my code to this:

1
2
3
4
5
6
7
8
	for (int i = 0; i < 20; i++)
	{
		form = rand() % 5;
		pos = rand() % 7;
		
		cout << "pos = " << pos << "\t";
		cout << "form = " << form << endl;
	}


All I did was switch lines 3 and 4. Now the first number isn't 0 every time any more. So weird. I have no idea why that would make a difference.
Try temporarily putting the call to srand() right before the calls to rand(). This will guard against Init() and load_files() calling srand() themselves.

Also, try printing out the full value returned by rand() to see how random it is.
Seems pretty random, right?

It really. Consider the frequency of each value of pos:
value frequency
0 5
1 1
2 1
3 5
4 4
5 1
6 3
I think this is just how some implementations of srand/rand works. rand are not really supposed to be random between calls to srand, so it's not really a bug or anything. It will get more random after you have called rand a few times so to fix your problem you could call rand in a loop before you start using it.
1
2
3
4
5
srand(static_cast<unsigned int> (time(0)));
for (int i = 0; i < 100; i++)
{
	rand();
}

Topic archived. No new replies allowed.