generate random number in a range c++ [duplicate] - c++

This question already has answers here:
How does modulus and rand() work?
(4 answers)
Closed 8 years ago.
I'm using the ncurses library to build a game. I'm having trouble generating the correct random numbers. The while loop below needs to keep generating random numbers until they are between 1 and 45(this is my y-axis limits on the standard screen). I can't figure out what I'm doing wrong because the while loop condition looks fine to me. The problem is that while loop starts running infinitely. Im not doing anything but printing the generated numbers at the end as i just want to see that the correct numbers are generated. can anyone please help me with this problem? The following is my int main.
int main()
{
int r,c,x=0;
initscr();
raw();
keypad(stdscr, TRUE);
noecho();
//mvprintw(22,45,"<");
getmaxyx(stdscr,r,c);
int n,n2 = 0;
while((n<1)||(n>45)){
srand (time(NULL));
n = rand();
srand (time(NULL));
n2 = rand();
}
mvprintw(4,10,"First Random Number: %d\n", n);
mvprintw(5,10,"Second Random number: %d\n", n2);
getch();
endwin();
return 0;
}

This is how you can do it in C++:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 gen( rd());
std::uniform_int_distribution<> dis( 1, 45);
for (int n=0; n<1000; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
Using rand() % x is a flawed design because of the bias introduced be dividing a range not evenly. You can read this to learn more about the bias introduced by rand() % x.

You want to call srand once at the start of things and then use modulus to bring rand results into your range, something like:
srand(time(NULL));
n = rand() % 45 + 1;
n2 = rand() % 45 + 1;

Just like #unholySheep commented, rand() returns a value between 0 and RAND_MAX, which it a huge value. Therefore, it is very unlikely you will get quickly a value between 1 and RAND_MAX.
Therefore, the solution is to do the reminder of the division by the number you want:
n = 1 + rand() % 45;
You do not even need a while.

You can get a random number between 1 and 45 inclusive with:
n = rand() % 45 + 1;
It won't be perfect in terms of distribution but it'll be close enough for anyone who's neither a statistician nor a cryptographer, in which case you probably would be using real random numbers.
You should also call srand() once, at the start of your program somewhere, rather than multiple times, especially if you're using the current time to seed it.
Doing it multiple times within the same second will give you a decidedly non-random sequence such as:
42, 42, 42, 42, 42, 42, 42, ...

Related

Broken random number generator? [duplicate]

This question already has answers here:
Random numbers in C
(10 answers)
How can I generate different random numbers for each player?
(3 answers)
Closed 4 years ago.
So I was creating a program that would call a function and return 0 or 1 (0 meaning tails and 1 meaning heads) and then use that to print the outcome of 100 flips.
It seemed simple enough thinking I could use srand(time(NULL)) to seed rand() with constantly varying seeds. Here was my first crack.
#include <stdio.h>
#include <stdlib.h>
int flip();
int main(void) {
int heads = 0;
int tails = 0;
for (short int count = 1; count <= 100; ++count) {
int number = flip();
if (number == 0) {
printf("%s", "Tails");
++tails;
}
else if (number == 1) {
printf_s("%s", "Heads");
++heads;
}
}//end for
printf_s("\n%d Tails\n", tails);
printf_s("%d Heads", heads);
}//end main
int flip(void) {
srand(time(NULL));
int number = (int)rand();
printf("%d", number%2);
return number%2;
}//end flip
I would run the program and my rand() value would always be a five digit integer repeated in each iteration of the for statement (i.e 15367, 15745, or 15943).
I messed around until I discovered changing srand(time(NULL)) to srand(time(NULL)*time(NULL)/rand()) did the trick.
My only thought is that the time between each for iteration is so small the the time(NULL) part of the srand() function doesn't change enough to feed a different seed value.
I also tried srand(time(NULL)/rand()), however, this produced the same result (52 heads 48 tails) every time I ran the program (20+times); however, the rand() values were all different from each other.
I do not know why these things happened, or why the final srand(time(NULL)*time(NULL)/rand()) function worked, and I would love it if someone could explain!
The reason is, that time(NULL) changes only once per second!
This means, that you seed the random number generator 100 times with the same seed.
A better way is to seed the RNG only once at start of the process (at the head of main(), then you should get different values.
If you start your program more often than once a second, you could also seed it with
srand(time(NULL)+getpid());
or similar.

Generation of random number(within a limit) code overshooting the upper limit [duplicate]

This question already has answers here:
Random number c++ in some range [duplicate]
(6 answers)
Closed 6 years ago.
My Computer science C++ book says that to generate random numbers with a lower limit (in this case, 15)and upper limit(in this case, 50), we have to use the following code. But when I used it I got the output as 56,32,49,15. Is there a reason why the program is giving results that overshoot the upper limit or is the code wrong.
#include <iostream>
#include <stdlib.h>
using namespace std;
int main(){
int i,rdno;
for(i=1;i<5;++i){
rdno=(rand()%50)+15;
cout <<rdno<<endl;
}
return 0;
}
If you want to generate a number in [a;b) use
rdno = rand() % (b-a) + a
Here: rdno = (rand()%50) you assign a pseudo-random number from 0-49. If you add 15, you get numbers from 15 to 64. If you want the numbers from 15 to 50, you can do it for example like this: rdno = (rand()%36) + 15.
EDIT: You need to use %36, as the highest number you want is 50. You can get it, when rand() generates 35, then 35%36 equals 35, and 35+15 equals 50. If you used %35, the highest number you can get is 49.
The best way to generate a random number in C that is between [x, y] such that y < 32768 is the following:
int random(int low, int high) {
return rand() % (high - low + 1) + low;
}
Notice the +1 at the modulus operator, this is to allow inclusion of 50. Without it, your range becomes [15, 50).
Sample run: http://ideone.com/Q6l0e5
For a C++ solution, please look at this: std::unfirom_int_distribution
Because the result of rand() % 50 is added to 15. So your range is 15-65.
Your range really is 35 (or 36 if inclusive) so you could change it to:
15 + (rand() % 35)
But really though, if you have access to C++11 use <random>:
#include <random>
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> dis(15, 50);
int random_integer = dis(rng);

How to generate negative random integer in c++

I wrote a function that takes integers. It won't crash if the user types for example, -5, but it will convert it into positive =-(
int getRandoms(int size, int upper, int lower)
{
int randInt = 0;
randInt = 1 + rand() % (upper -lower + 1);
return randInt;
}
What should I change in the function in order to build random negative integers?
The user inputs the range.
There are two answers to this, if you are using C++11 then you should be using uniform_int_distribtion, it is preferable for many reasons for example Why do people say there is modulo bias when using a random number generator? is one example and rand() Considered Harmful presentation gives a more complete set of reasons. Here is an example which generates random integers from -5 to 5:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 e2(rd());
std::uniform_int_distribution<int> dist(-5, 5);
for (int n = 0; n < 10; ++n) {
std::cout << dist(e2) << ", " ;
}
std::cout << std::endl ;
}
If C++11 is not an option then the method described in C FAQ in How can I get random integers in a certain range? is the way to go. Using that method you would do the following to generate random integers from [M, N]:
M + rand() / (RAND_MAX / (N - M + 1) + 1)
For a number in the closed range [lower,upper], you want:
return lower + rand() % (upper - lower + 1); // NOT 1 + ...
This will work for positive or negative values, as long as upper is greater than or equal to lower.
Your version returns numbers from a range of the same size, but starting from 1 rather than lower.
You could also use Boost.Random, if you don't mind the dependency. http://www.boost.org/doc/libs/1_54_0/doc/html/boost_random.html
You want to start by computing the range of the numbers, so (for example) -10 to +5 is a range of 15.
You can compute numbers in that range with code like this:
int rand_lim(int limit) {
/* return a random number in the range [0..limit)
*/
int divisor = RAND_MAX/limit;
int retval;
do {
retval = rand() / divisor;
} while (retval == limit);
return retval;
}
Having done that, getting the numbers to the correct range is pretty trivial: add the lower bound to each number you get.
Note that C++11 has added both random number generator and distribution classes that can take care of most of this for you.
If you do attempt to do this on your own, when you reduce numbers to a range, you pretty much need to use a loop as I've shown above to avoid skew. Essentially any attempt at just using division or remainder on its own almost inevitably introduces skew into the result (i.e., some results will happen more often than others).
You only need to sum to the lower-bound of the range [lbound, ubound]:
int rangesize = ubound - lbound + 1;
int myradnom = (rand() % rangesize) + lbound;

Identical Random Numbers Generated in C++

I've been banging my head against this for half an hour now, and have NO idea what's wrong.
I'm trying to generate a list of 10 random numbers, 1-100. But when I run it they all come out the same number. It is very frustrating! I thought that it was because the number was still stored in the RAM, but after re-randomizing the random number and the variable three times, it still comes out with the same number. What am I doing wrong?
Code:
main() {
int i;
int randnum;
srand(time(NULL));
randnum = rand() % 2;
for (i = 0; i < 10; i++) {
srand(time(NULL));
randnum = rand() % 100 + 1;
srand(time(NULL));
rand();
list[i] = randnum;
srand(time(NULL));
randnum = rand() % 100 + 1;
srand(time(NULL));
rand();
}
srand(time(NULL));
randnum = rand() % 100 + 1;
}
Don't call srand() more than once. This code likely takes less than a second to execute, so every time you call srand(time(NULL)) when time is measured in seconds on your implementation, you just reset the pseudo random number generator to the same seed, so all your numbers come out the same.
Don't reinitialize the generator with srand(time(NULL)). Use it only once, at the beginning of your code.
What you're doing wrong is that you're resetting the random number generator's state.
The reason its not obvious is because you're using time. time returns time_t, which, according to the standard is "the implementation’s best approximation to the current calendar time". This generally represents the number of seconds since 00:00 hours, Jan 1, 1970 UTC. Now, your code will likely execute within a millisecond, so all your time calls return the same value.
So your code is equivalent to:
int const somenum = time(NULL);
srand(somenum); //reset state using some seed.
//rand() will always produce the same value after an
// srand call of the same seed.
randnum = rand() % 100 + 1;
srand(somenum); //reset state using some seed.
randnum = rand() % 100 + 1;
srand(somenum); //reset state using some seed.
randnum = rand() % 100 + 1;
srand(somenum); //reset state using some seed.
randnum = rand() % 100 + 1;
To test this, wait for a keypress between each call to rand and you will see they are different.
The way to fix this is to only call srand(time(NULL)) once, at the start.
Now, in C++11, there is another way:
#include <iostream>
#include <random>
int main()
{
const int rand_max = 20;
std::default_random_engine rng(std::random_device{}());
std::uniform_int_distribution<> dist(0, rand_max);
std::cout<<"This will always be as random a number as your hardware can give you: "<<dist(rng)<<std::endl;
return 0;
}
std::random_device makes use of a built in hardware random number generator if available, so you don't have to worry about seeding with time. If you really do want a pseudo random number, then just use a different random number generator.
You can also control the random number distribution in C++11.

C++ generation of random numbers [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to generate different random number in a loop in C++?
This is my code:
for(i=0;i<10;i++)
{
srand ( time(NULL) );
cout<<time(NULL);
max=100,min=0;
for(j=0;j<3;j++)
{
cout<<(( (rand() % (max - min + 1)) + min)%5);
}
}
Now i get the output:
1357207288 0 1 4
1357207289 0 1 4
1357207290 0 1 4
and so on. I want to get different random numbers each time. How can I achieve this.
The reason you get the same repeatedly is because you initialize it with the same seed each time. That is, since you are performing so few operations, not a single second has passed since the first iteration of the loop to the last one. Hence, time(nullptr) will return the same for each iteration.
To solve this, move srand ( time(NULL) ); outside of the loop, which will mean setting the random seed only once.
srand ( time(NULL) );
for(int i=0;i<10;i++)
{
cout<<time(NULL);
int max=100;
for(int j=0;j<3;j++)
{
cout<<(( (rand() % (max - min + 1)) + min)%5);
}
}
You must move srand() outside of your loop, otherwise you receive the same numbers.
srand ( time(NULL) );
for(i=0;i<10;i++)
{
cout<<time(NULL);
max=100,
for(j=0;j<3;j++)
{
cout<<(( (rand() % (max - min + 1)) + min)%5);
}
}
If you don't you will use the same seed since the time will not change in the nanoseconds your program takes to execute.
srand(time(NULL));
printf("%d", rand() % 10+1);
for(i=1; i<rand()% max_length; i++) {
printf("%ld", rand() % 10);
}
This will generate random numbers (also random length of them).
You get the same results even with srand() out of the loop because in C the generation algorithm used by rand is guaranteed to only be advanced by calls to this function. In C++, this constraint is relaxed, and a library implementation is allowed to advance the generator on other circumstances (such as calls to elements of <random>). Put a sleep inside the loop and see what happens.
Obviously in plain C this doesn't happen.
However, boost libraries offers you some good PRNG functionality. Use it instead of the broken srand(time(NULL));