I am having trouble grasping the concept of rand() and srand() in c++. I need to create a program that displays two random numbers, have the user enter a response, then match the response with a message and do this for 5 times.
My question is how do I use it, the instructions say I can't use the time() function and that seems to be in every tutorial online about rand().
this is what I have so far.
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
int main()
{
int seed;
int response;
srand(1969);
seed=(rand()%10+1);
cout<<seed<<" * "<<seed<<" = ";
cin>>response;
cout<<response;
if(response==seed*seed)
cout<<"Correct!. you have correctly answered 1 out of 1."<<endl;
else
cout<<"Wrong!. You have correctly answered 0 out of 1."<<endl;
This just outputs something like 6*6 or 7*7, I thought the seed variable would be not necessary different but not the same all the time?
This is what the output should look like:
3 * 5 =
34
Wrongo. You have correctly answered 0 out of 1.
8 * 1 =
23
Wrongo. You have correctly answered 0 out of 2.
7 * 1 =
7
Correct! You have correctly answered 1 out of 3.
2 * 0 =
2
Wrongo. You have correctly answered 1 out of 4.
8 * 1 =
8
Correct! You have correctly answered 2 out of 5.
Final Results: You have correctly answered 2 out of 5 for a 40% average.
and these are the requirements:
Your program should use rand() to generate pseudo-random numbers as needed. You may use srand() to initialize the random number generator, but please do not use any 'automatic' initializer (such as the time() function), as those are likely to be platform dependent. Your program should not use any loops.
By the way, since this is C++, you should really seek to use std::uniform_int_distribution, e.g.
#include <functional>
#include <random>
...
auto rand = std::bind(std::uniform_int_distribution<unsigned>(0, 10),
std::default_random_engine());
Now, you can just use rand() to generate a number in the desired interval.
The way you are using it now seems fine. The reason why all the tutorials use time() is because the numbers will be different every time you run your program. So, if you use a fixed number, every time your program runs, the output (number generation) will be the same. However, according to your requirements this doesn't seem to be a problem (if you need the random generation to be different every time you run your program, please specify that in your question).
However, rand()%10+1 is a range from 1 to 10 and not 0 to 10 like you want.
AFTER EDITS
To get the desired output, all you need is to make two seeds like so:
seed1=(rand()%11);
seed2=(rand()%11);
cout<<seed1<<" * "<<seed2<<" = ";
Also, you can ask the user for a seed and then pass that to srand to make each run more random.
About the requirements:
please do not use any 'automatic' initializer (such as the time()
function), as those are likely to be platform dependent
std::time is a standard C++ function in the <ctime> header. I do not understand why it matters if the result is platform dependent.
Your program should not use any loops.
This is also a very strange requirement. Loops are fundamental building blocks of any program. The requirements seem very strange to me, I would ask your professor or teacher for clarification.
On windows you can use GetTickCount() instead if time().
You could use rand_s which doesn't need to be seeded.
On *nix systems you can utilize /dev/random.
(How to use /dev/random)
You use srand() to seed the random function. This is necessary otherwise you'd get the same sequence of number with each run, and each call to rand()
You can seed rand with whatever you please. You'll find most tutorials use the current time as a seed as the number returned is usually different with each run of the program.
If you truly can't use the time() functionality, I would pass the seed as a command line argument.
int main(int argc, char* argv[])
{
srand(atoi(argv[1])); // Seed with command line argument.
}
Related
So i've been building a simple console game in c++ where I am using the rand() function from stdlib.h. I have recognized that i got different results from the rand function if I was executing the program in debug mode or without debugging.
Here is my code where I use the rand function:
void Game::SelectHiddenWord(Fstring &word) {
std::vector<Fstring> WordList{ "plan","planet","planes","radios","gamers","images",
"amigos","micros","macros","frogs","raids","roads","paris","smog","cars","macs","scam","some","farm","fair",
"jam","rat","map","zig","zag","isogram","amorist","roaming","mirages","soaring","cargos","disarm","isobar"
};
int32 Length = WordList.size();
int32 randomNumber = std::rand()%Length;
word = WordList.at(randomNumber);
}
So basically I have a wordlist with isograms and I am using the rand function to generate an integer which I will use as my index when selecting a word from the wordlist. I found that every time I was executing the program the randomNumber integer was always 14 which would then give me the word "smog" from the wordlist. First I thought that this maybe was a bug since I've read that the rand() function isn't the best to use to generate random numbers. So I started the program in debug mode and I found out that I the randomNumber integer now was 32 which would give me the word "disarm" from the wordlist. And this happend every time I was using debugmode.
So on startup without debugging I always get the word "smog" and on startup with debugging I always get the word "disarm" so I can really just play around with two words.
So is this some sort of bug with the rand() function that it will behave differently when executing the program in debug mode and without debug mode?
I'm trying to learn c++ and I couldn't find any information about the rand function behaving differently so I do not know how I can fix this issue. So if any of you guys know how to fix this issue, so that the rand() function will behave the same and generate the same number independently if I am using debug mode or without debugging. Or maybe I need to use another function to generate my random numbers?
Any help will be appreciated!
Edit:
I do not want to know why the rand() function generates the same value everytime.
When I start the program without debugging the rand() always generates the number 14, and I want this to happen. But if I start the program in debug mode the rand() always generates the number 32. But I want the rand function to always generate the number 14, independently if I execute the program in debug mode or without debugging.
So the question is about why the rand() function is behaving differently and generating different numbers if it is executed with or without debugging. I don't even know if it's possible to answer this, maybe it could just be something with my machine.
My testing code:
void Game::Print() {
Fstring HIDDEN_WORD{}; //This MUST be an isogram
SelectHiddenWord(HIDDEN_WORD);
MyHiddenWord= HIDDEN_WORD;
std::cout << MyHiddenWord << std::endl; //This prints "smog" to the screen if I start the program without debugging,
//and if I debug the program it prints "disarm" to the screen
My main method:
Game MyGame;
int main() {
MyGame.Print();
}
I am using Microsoft Visual C++ compiler.
Addressing why rand() behaves differently between in debug mode is a question for your compiler vendor. How it works internally is implementation-defined (i.e. up to the compiler's creators). From cppreference:
There are no guarantees as to the quality of the random sequence
produced. [...]
rand() is not recommended for serious random-number generation needs.
It is recommended to use C++11's random number generation facilities
to replace rand().
Clearly rand() is a bit old-fashioned, which I'll address toward the end of my answer. As to why you're seeing the same value during every run of the program, this is not a bug with rand(). rand() is a pseudo-random number generator that can generate seemingly random numbers, but in a completely deterministic manner. In order to get different results on every run, you need to seed the random number generator with something somewhat unpredictable, like, say, the current time. This is done as follows.
#include <cstdlib>
#include <ctime>
int main(){
srand(time(0));
// rand() will now behave differently on each run of the program
}
This is also explained here. It is also important to note that you should only call srand once at the start of your program. Calling srand multiple times within the same second will result in the same seed, and thus the same random sequence from rand, as explained here.
If you want to be most correct, C++11 now offers a good random number generation library that you should consider using. An example usage could look like:
#include <random>
std::random_device rd; // reliable random seed generator
std::default_random_engine randengine { rd() }; // global rng, seeded with random device
...
void Game::SelectHiddenWord(Fstring &word) {
// NOTE: this vector can be static const if it never changes, to avoid
// constructing and destructing it every function call
static const std::vector<Fstring> WordList{ "plan","planet","planes","radios","gamers","images", "amigos","micros","macros","frogs","raids","roads","paris","smog","cars","macs","scam","some","farm","fair","jam","rat","map","zig","zag","isogram","amorist","roaming","mirages","soaring","cargos","disarm","isobar"};
// define distribution as [ 0, WordList.size() )
std::uniform_int_distribution<size_t> dist { 0, WordList.size() - 1 };
word = WordList.at(dist(randengine));
}
I'm still a little confused by one thing you mentioned:
But I want the rand function to always generate the number 14 [...]
If this is really what you want, you can replace every rand() with 14 :-)
Okay I'm starting to lose my mind. All I want to do is random a number between 0 and 410, and according to this page, my code should do that. And since I want a random number and not a pseudo-random number, I'm using srand() as well, in a way that e.g. this thread told me to do. But this isn't working. All I get is a number that is depending on how long it was since my last execution. If I e.g. execute it again as fast as I can, the number is usually 6 numbers higher than the last number, and if I wait longer, it's higher, etc. When it reaches 410 it goes back to 0 and begins all over again. What am I missing?
Edit: And oh, if I remove the srand(time(NULL)); line I just get the same number (41) every time I run the program. That's not even pseudo random, that's just a static number. Just copying the first line of code from the article I linked to above still gives me number 41 all the time. Am I the star in a sequel to "The Number 23", or have I missed something?
int main(void) {
srand(time(NULL));
int number = rand() % 410;
std::cout << number << std::endl;
system("pause");
}
That is what you get for using deprecated random number generation.
rand produces a fixed sequence of numbers (which by itself is fine), and does that very, very badly.
You tell rand via srand where in the sequence to start. Since your "starting point" (called seed btw) depends on the number of seconds since 1.1.1970 0:00:00 UTC, your output is obviously time depended.
The correct way to do what you want to do is using the C++11 <random> library. In your concrete example, this would look somewhat like this:
std::mt19937 rng (std::random_device{}());
std::uniform_int_distribution<> dist (0, 409);
auto random_number = dist(rng);
For more information on the evils of rand and the advantages of <random> have a look at this.
As a last remark, seeding std::mt19937 like I did above is not quite optimal because the MT's state space is much larger than the 32 bit you get out of a single call to std::random_device{}(). This is not a problem for toy programs and your standard school assignments, but for reference: Here is my take at seeding the MT's entire state space, plus some helpful suggestions in the answers.
From manual:
time() returns the time as the number of seconds since the Epoch,
1970-01-01 00:00:00 +0000 (UTC).
Which means that if you start your program twice both times at the same second you will initialize srand with same value and will get same state of PRNG.
And if you remove initialization via call to srand you will always get exactly same sequence of numbers from rand.
I'm afraid you can't get trully random numbers there. Built in functions are meant to provide just pseudo random numbers. Moreover using srand and rand, because the first uses the same approach as the second one. If you want to cook true random numbers, you must find a correct source of entrophy, working for example with atmospheric noise, as the approach of www.random.org.
The problem here consists in the seed used by the randomness algorithm: if it's a number provided by a machine, it can't be unpredictable. A normal solution for this is using external hardware.
Unfortunately you can't get a real random number from a computer without specific hardware (which is often too slow to be practical).
Therefore you need to make do with a pseudo generator. But you need to use them carefully.
The function rand is designed to return a number between 0 and RAND_MAX in a way that, broadly speaking, satisfies the statistical properties of a uniform distribution. At best you can expect the mean of the drawn numbers to be 0.5 * RAND_MAX and the variance to be RAND_MAX * RAND_MAX / 12.
Typically the implementation of rand is a linear congruential generator which basically means that the returned number is a function of the previous number. That can give surprisingly good results and allows you to seed the generator with a function srand.
But repeated use of srand ruins the statistical properties of the generator, which is what is happening to you: your use of srand is correlated with your system clock time. The behaviour you're observing is completely expected.
What you should do is to only make one call to srand and then draw a sequence of numbers using rand. You cannot easily do this in the way you've set things up. But there are alternatives; you could switch to a random number generator (say mersenne twister) which allows you to draw the (n)th term and you could pass the value of n as a command line argument.
As a final remark, I'd avoid using a modulus when drawing a number. This will create a statistical bias if your modulo is not a multiple of RAND_MAX.
Try by change the NULL in time(NULL) by time(0) (that will give you the current système time). If it doesn't work, you could try to convert time(0) into ms by doing time(0)*1000.
This question already has answers here:
What does 'seeding' mean?
(4 answers)
Closed 6 years ago.
What is a seed in terms of generating a random number?
I need to generate hundreds to thousands of random numbers, I have read a lot about using a "seed". What is a seed? Is a seed where the random numbers start from? For example if I set my seed to be 5 will it generate numbers from 5 to whatever my limit is? So it will never give me 3 for example.
I am using C++, so if you provide any examples it'd be nice if it was in C++.
Thanks!
What is normally called a random number sequence in reality is a "pseudo-random" number sequence because the values are computed using a deterministic algorithm and probability plays no real role.
The "seed" is a starting point for the sequence and the guarantee is that if you start from the same seed you will get the same sequence of numbers. This is very useful for example for debugging (when you are looking for an error in a program you need to be able to reproduce the problem and study it, a non-deterministic program would be much harder to debug because every run would be different).
If you need just a random sequence of numbers and don't need to reproduce it then simply use current time as seed... for example with:
srand(time(NULL));
So, let's put it this way:
if you and your friend set the seed equals to the same number, by then you and your friend will get the same random numbers. So, if all of us write this simple program:
#include<iostream>
using namespace std;
void main () {
srand(0);
for (int i=0; i<3; i++){
int x = rand()%11; //range between 0 and 10
cout<<x<<endl;
}
}
We all will get the same random numbers which are (5, 8, 8).
And if you want to get different number each time, you can use srand(time())
I heard that computation results can be very sensitive to choice of random number generator.
1 I wonder whether it is relevant to program own Mersenne-Twister or other pseudo-random routines to get a good number generator. Also, I don't see why I should not trust native or library generators as random.uniform() in numpy, rand() in C++. I understand that I can build generators on my own for distributions other than uniform (inverse repartition function methor, polar method). But is it evil to use one built-in generator for uniform sampling?
2 What is wrong with the default 'time' seed? Should one re-seed and how frequently in a code sample (and why)?
3 Maybe you have some good links on these topics!
--edit More precisely, I need random numbers for multistart optimization routines, and for uniform space sample to initialize some other optimization routine parameters. I also need random numbers for Monte Carlo methods (sensibility analysis). I hope the precisions help figure out the scope of question.
Well, I can't speak about C++, but Python uses the Mersenne Twister. So there's no need to implement your own in Python. Also, Python only uses the system time as a seed if there's no other source of randomness; this is a system-dependent issue. See also the os.urandom docs about this.
It's fun to write your own, though. The pseudocode on the MT Wikipedia page is clear and easy-to-implement.
Of course the usual caveats apply. This is not a cryptographic random number generator. Not all permutations of a largish list can be generated by random.shuffle, and so on. But for the uses you specify, it's likely that the Mersenne Twister is fine.
In C++ the <random> library probably provides all you need. It has 3 different PRNG template algorithms including mersenne twister, 3 adaptors for use on top of those, 9 concrete random number generators, plus access to your system's non-deterministic random number source.
On top of that it has 20 random number distributions that include uniform, normal, bernoulli, poisson, and sampling distributions.
Here's a (slightly modified) example from Stroustrup's C++11 FAQ.
#include <iostream>
#include <random>
#include <string>
#include <vector>
#include <functional>
int main()
{
auto rand = std::bind(
std::normal_distribution<>(15.0,4.0),
std::mt19937());
std::vector<int> output(32);
for (int i = 0; i<400; ++i)
++output[rand()];
for (int i = 0; i<output.size(); ++i)
std::cout << i << '\t' << std::string(output[i],'*') << '\n';
}
0
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
At least in C++, rand is sometimes rather poor quality, so code should rarely use it for anything except things like rolling dice or shuffling cards in children's games. In C++ 11, however, a set of random number generator classes of good quality have been added, so you should generally use them by preference.
Seeding based on time can work fine under some circumstances, but not if you want to make it difficult for somebody else to duplicate the same series of numbers (e.g., if you're generating nonces for encryption). Normally, you want to seed only once at the beginning of the program, at least in a single-threaded program. With multithreading, you frequently want a separate seed for each thread, in which case you need each one to start out unique to prevent generating the same sequences in all threads.
Python's random.uniform() is fine. Actually it already uses Mersenne-Twsiter.
However, you'd better avoid C and C++'s rand(), since it often produce bad random numbers (See also What common algorithms are used for C's rand()?). Even worse, on Windows the RAND_MAX is only 0x7fff so you can't get more than 32768 distinct values. If you could use C++11, check the new <random> library which contains many random number generators, including MT-19937. Otherwise, you could still use Boost.Random.
Seeding a random number generator with time is fine, as long as (1) you're not working with serious crypotography (you shouldn't use Mersenne-Twsiter in crypotography anyway), and (2) you can guarantee that it is impossible to have two seeds with the same time value, which will cause the same sequence be generated.
My random numbers that output, output in the same sequence every time I run my game. Why is this happening?
I have
#include <cstdlib>
and am using this to generate the random numbers
randomDiceRollComputer = 1 + rand() % 6;
You need to seed your random number generator:
Try putting this at the beginning of the program:
srand ( time(NULL) );
Note that you will need to #include <ctime>.
The idea here is to seed the RNG with a different number each time you launch the program. By using time as the seed, you get a different number each time you launch the program.
You need to give the randum number generator a seed. This can be done by taking the current time, as this is hopefully some kind of random.
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
int r;
srand(time(0));
r = rand();
return 0;
}
The rand() function is specifically required to produce the same sequence of numbers when seeded with a given seed (by calling srand()); each possible seed value specifies a sequence. And if you never call srand(), you get the same sequence you would have gotten by calling srand(1) before any call to rand().
(This doesn't apply across different C or C++ implementations.)
This can be useful for testing purposes. If there's a bug in your program, for example, you can reproduce it by re-running it with the same seed, guaranteeing that (barring other unpredictable behaviors) you'll get the same sequence of pseudo-random numbers.
Calling srand(time(NULL)) is the usual recommended way to get more or less unpredictable pseudo-random numbers. But it's not perfect. If your program runs twice within the same second, you'll probably get the same sequence, because time() (typically) has a resolution of 1 second. And typical `rand() implementations are not good enough for cryptographic use; it's too easy for an attacker to guess what numbers you're going to get.
There are a number of other random number implementations. Linux systems have two pseudo-devices, /dev/random and /dev/urandom, from which you can read reasonably high-quality pseudo-random byte values. Some systems might have functions like random(), drand48(), and so forth. And there are numerous algorithms; I've heard good things about the Mersenne Twister.
For something like a game, where you don't expect or care about players trying to cheat, srand(time(NULL)) and rand() is probably good enough. For more serious purposes, you should get advice from someone who knows more about this stuff than I do.
Section 13 of the comp.lang.c FAQ has some very good information about pseudo-random number generation.
Pseudorandom number generators take a starting number, or seed, and then generate the next number in the sequence from this. That's why they're called pseudorandom, because if they always use the same starting value, they will generate the same sequence of numbers like the C standard lib generator does. This can be fixed by giving the generator a starting value that will change the next time the program is run like the current time.
Anyway, the code you're looking for like others have said is:
srand(time(0)); //Seed the generator, give it a starting value