Sign in to follow this  
LordUlquiorra

rand()

Recommended Posts

LordUlquiorra    100
Hello there, this is my first post on GD and I'm in need of some help. I've been studying C++ for about 2 days now and I decided to start practicing it a bit. I do have SOME background programming experience, but not for anything like C++. I'm also looking for tips so I don't develop bad habits.
#include <iostream>
#include <cstdlib>
using std::rand;
using std::cout;
using std::cin;

int main()
{
	int answer = rand();
	int num;
	do
	{
		cout << "Please enter a number.\n";
		cin >> num;
		
		if( num == answer )
		{
			cout << "Wow, you got it right.";
			return 0;
		}
		else if( num > answer )
			{
			cout << "Too high.\n";
			}	
		else 
			cout << "Too low.\n";
	} while( 1 );
}
The problem is the answer variable is ALWAYS 41, I don't know where I went wrong with this, but it'd be alot of help if someone at least pointed me in the right direction.

Share this post


Link to post
Share on other sites
leeor_net    343
That will work but since you're learning it would be helpful to understand why it works.

The problem with rand() is that it's not a true random number generator. I forget exactly the semantics but suffice it to say that it will always generate the same numbers.

The function srand() stands for Seed Rand. You're basically seeding the pseudo-random number generator (PRNG) with some value. Most of the time you can use the internal clock cycle value to do this and it will provide you with random enough values to work with.

Seeding the PRNG once in your program isn't always as effective as you may need. Note that using the PRNG can be slow so if you're looking for high performance try to avoid using srand() and rand() during program execution loops (like a game rendering loop) -- I like to create a list of maybe 1000 pregenerated random numbers and just iterate through that but such a solution may be total overkill for your purposes.

Share this post


Link to post
Share on other sites
LordUlquiorra    100
Thank you both for your input, I got it to work but I keep getting this warning.
warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data


#include <iostream>
#include <ctime>
#include <cstdlib>
using std::rand;
using std::srand;
using std::cout;
using std::cin;

int main()
{
srand( time( 0 ) );
int num = 1 + rand() % 10;
int answer;
do
{
cout << "Please enter a number.\n";
cin >> answer;

if( answer == num )
{
cout << "Wow, you got it right.";
return 0;
}
else if( answer > num )
{
cout << "Too high.\n";
}
else
cout << "Too low.\n";
} while( 1 );
}

Share this post


Link to post
Share on other sites
CodeDemon    363
Quote:
Original post by leeor_net
Seeding the PRNG once in your program isn't always as effective as you may need. Note that using the PRNG can be slow so if you're looking for high performance try to avoid using srand() and rand() during program execution loops (like a game rendering loop) -- I like to create a list of maybe 1000 pregenerated random numbers and just iterate through that but such a solution may be total overkill for your purposes.


The rand and srand functions aren't as slow as you believe, unless you're trying to write games for something with a 16MHz processor. Take a look at some source code for those functions. The slowest thing with rand is the acquisition of the mutex for thread-safe implementations.

I'd suggest using a different PRNG rather that the one in ANSI/ISO C 89/99 for different reasons. rand only has 16-bits of precision. rand only has a single state, and so if you're trying to model certain distributions of random numbers in different parts of your program, you will want to use separate PRNG state.

I suggest going with a multiply-with-carry PRNG, they're lightweight (only 64-bits of state needed) and as fast as Mersenne Twister (which requires 2KB of state).

Share this post


Link to post
Share on other sites
fastcall22    10840
Quote:
Original post by LordUlquiorra
warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data


The message in detail states that a time_t (a signed 64-bit long integer1) returned by time() may not fit into the target data type expected by srand(), an unsigned 32-bit integer. The range from a signed 64-bit value ranges from -9223372036854775808 to 9223372036854775807, while the 32-bit unsigned integer only ranges from 0 to 4294967295. The compiler will implicitly make the conversion for you, and will let you know when it does. If you do not wish the compiler to notify you, you can place #pragma warning( disable : 4244 ) before your code.

Back on topic, you can safely ignore that warning since you just need something varying with the current time to seed your PRNG. However, to remove the warning, you can let your compiler know that you acknowledge the possible loss of data by use of type-casting. There are two ways to cast: static_cast<unsigned int>( time(0) ), (unsigned int)time(0), or unsigned int( time(0) ). The first is preferred C++-style casting, while the last two are variants of C-style casting. Use whichever method you find easier to read.


Oh, and for future reference: You can get detailed information on compiler errors and warnings on the MSDN library, or by google'ing with the terms msdn error code.

[1] According to MSDN.

[Edited by - _fastcall on June 21, 2009 1:39:02 AM]

Share this post


Link to post
Share on other sites
Denzin    100
you should include a break;
command in your num == answer if condition since you are creating an infinite loop with while(1).

Share this post


Link to post
Share on other sites
fastcall22    10840
Quote:
Original post by Denzin
you should include a break;
command in your num == answer if condition since you are creating an infinite loop with while(1).


If you look closely, there's a return 0; when answer == num, which is equivalent to a break; (on the generated-code level). As long as the OP remembers that the program exits when answer == num, he should be fine. If not, he'll most likely wonder why code added after the loop won't be executed. [lol]

Share this post


Link to post
Share on other sites
pulpfist    528
Just as a side note, there may be times when you actually want to generate the same sequence of random numbers as the last time. I'm sure you can imagine how the seed can come in handy in these situations. Basically you can feed the srand function with the same seed you used at program start, and you will get the exact same sequence of "random" numbers generated all over again.

Share this post


Link to post
Share on other sites
leeor_net    343
I would highly recommend against using a "#pragma warning( disable : 4244 )" for beginners for two reasons:

1) It will disable warnings where the user genuinely made a mistake and;
2) It's compiler dependant and if one wants to develop cross-platform software (which I highly recommend, btw) than pragma's are not the way to disable messages.

Share this post


Link to post
Share on other sites
fastcall22    10840
Quote:
Original post by leeor_net
1) It will disable warnings where the user genuinely made a mistake


Could you explain what you mean by that? I understand it is sometimes an error to try to fit a value larger than a data type could hold, but I don't see how a conversion from double to float (for instance, as an argument for drawing a line in a graphics API) could be a "genuine mistake".

Quote:

2) It's compiler dependent and if one wants to develop cross-platform software (which I highly recommend, btw) than pragma's are not the way to disable messages.


From www.cplusplus.com: If the compiler does not support a specific argument for #pragma, it is ignored - no error is generated. Therefore, you'd just disabling warnings just for Visual Studio.

Instead of using a #pragma, you could go to the project properties in Visual Studio and append the warning number to the "Disable Specific Warnings" item under Configuration Properties -> C/C++ -> Advanced. But as leeor_net implied, it is better to be explicit than implicit with your castings.

Share this post


Link to post
Share on other sites
StarBP    100
Quote:
Original post by CodeDemon
I'd suggest using a different PRNG rather that the one in ANSI/ISO C 89/99 for different reasons. rand only has 16-bits of precision. rand only has a single state, and so if you're trying to model certain distributions of random numbers in different parts of your program, you will want to use separate PRNG state.

I suggest going with a multiply-with-carry PRNG, they're lightweight (only 64-bits of state needed) and as fast as Mersenne Twister (which requires 2KB of state).


Xorshift (http://en.wikipedia.org/wiki/Xorshift) is a very fast random number generator with a 128-bit period. Read the paper associated with it, though, as the code on Wikipedia uses incorrect numbers for the shifting (possibly resulting in a lower period).

Share this post


Link to post
Share on other sites

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