Broken random number generator? [duplicate] - c++

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.

Related

Random list of numbers

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int main()
{
int i;
int diceRoll;
for(i=0; i < 20; i++)
{
printf("%d \n", rand());
}
return 0;
}
This is the code I wrote in c (codeblocks) to get random numbers, the problem is I always get the same sequence: 41,18467,6334,26500 etc...
I'm still learning so please try to explain like you're talking with a 8 year old D:
You get the same sequence each time because the seed for the random number generator isn't set. You need to call srand(time(NULL)) like this:
int main()
{
srand(time(NULL));
....
Random number generators are pseudorandom. What this means is that they use some "algorithm" to come up with the next "random" number. In other words, if you start with the same seed to this algorithm, you get the same sequence of random numbers each time. To solve this, you have to make sure to seed your random number generator. Sometimes, it is desirable to use the same seed so that you may deduce if the logic of your program is working correct. Either way, one common way that folks seed their programs is through the use of time(NULL). time gives the time elapsed (in seconds) since the epoch time. What this means is that this function changes every second. Thus, if you seed your random number generator with (srand(time(NULL)) at the beginning of the program, you'll get a different random number sequence every different second that you run your program. Be sure not to seed for every random number that you request. Just do this once at the very beginning of your code and then leave it alone.
Your title says C# but I've answered with C++. You'll want to include ctime for this. It may also be beneficial to look at the new style of random number generation as rand() isn't very random these days. Look into #include random and make yourself an engine and distribution to pull random numbers through. Don't forget to seed there as well!
First of all, seed your random function by including <ctime> and calling srand(time(NULL));.
Secondly, you need a modulo if you're going to call rand(), for example: rand() % x will return a random number from 0 to x-1. Since you're simulating dice rolls, do rand() % 6 + 1.
The line srand((unsigned)(time(NULL)) must be outside the loop, must have this line just once in your code.
The modulo rand()%10 means you get any number starting from 0 going up to what you are modulo by -1. So in this case 0-9, if you want 1-10 you do: rand()%10 + 1
int main()
{
int i;
int diceRoll;
srand((unsigned)(time(NULL));
for(i=0; i < 20; i++)
{
printf("%d \n", rand() % 10); //Gets you numbers 0-9
}
return 0;
}

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

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, ...

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));

How do I generate totally a random number at a time?

I want to create 3 random number at a time (simultaneously). However, they returned me the same numbers at a time even though they are actually random. Example:
------------------------
Variable: A B C
------------------------
Time 1 : 5 5 5
Time 2 : 3 3 3
Time 3 : 9 9 9
------------------------
They suppose to be different numbers at all. From the observation, I can see that my code can only pick a random number at a time (interval 1 second). Here is my generator code that I'm using:
unsigned int CMain::GenerateRandom(int min, int max)
{
srand((unsigned)time(0));
unsigned int random_integer;
int lowest = min, highest = max;
int range = (highest - lowest) + 1;
random_integer = lowest + int(range * rand() / (RAND_MAX + 1.0));
return random_integer;
}
How could I generate a totally random numbers at a time? Please help.
Thank you.
Your issue here is you're resetting the random seed every call using the current time which you shouldn't do.
Call srand() once before querying any random numbers - that's all and more than enough.
Right now you always reset your random seed to the exact same value (as you use current time). Random numbers in PCs aren't really random at all. The same seed will always result in the same set of random numbers generated later on. This is intentional and used in e.g. savegames for games to always have the same things happen without having to save every random number generated, etc.
Don't call srand() each time you generate a new random number. Call it once at the start of your program and then just call rand() each time you need a new random number.
FYI: Values returned from rand() are not "totally random". They are pseudo-random numbers generated by an algorithm. (This is not related to your question though.)
The problem is that you are calling srand() for every iteration. Srand() is setting a seed based on the current timestamp. Therefore you only need to call srand() once, and just call rand() to generate a new pseudo-random number. I say pseudo-random because computers cannot generate truly random numbers.
Sample code:
#include <iostream>
#include <cstdlib>
int main()
{
int i, r;
srand(time(0));
for(i = 0; r <= 20000; i++)
r = rand();
return 0;
}
time(0) changes slowly. If you query GenerateRandom quickly you can get the same number multiple times.
But in general, that isn't a right way to generate random numbers. You want to seed the random number generator only once, before any other function uses it. Treat rand as a global singleton object. If any of your functions modifies its seed by calling srand, then the change will affect all other calls to rand.

C++ random number generator without repeating numbers

I have searched high and low for a type of function that turns this code
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
void ran(int array[], int max);
int main() {
printf("Today's lottery numbers are:\n");
for (int i = 0; i < 6; i++)
srand((unsigned)(NULL));
}
into a random number generator that ensures no repeating numbers can someone help me with it? after the check I plan to print it with printf("%d\n", rand()%50);
I just need a routine that makes sure its non repeating. Please If you can give me a routine I would be greatly relieved and will be sure to pay it forward.
Thanks. The libraries don't seem to be reading right on this scren but they are stdio, stdlib and time and im using namespace.
Why not just use what's already in the STL? Looking at your example code, and assuming it's somewhat representative of what you want to do, everything should be in there. (I assume you need a relatively small range of numbers, so memory wouldn't be a constraint)
Using std::random_shuffle, and an std::vector containing the integers in the range you wish your numbers to be in, should give you a sequence of unique random numbers that you need in your example code.
You will still have to call srand once, and once only, before using std::random_shuffle. Not multiple times like you're doing in your current code example.
If your range of random numbers is finite and small, say you have X different numbers.
Create an array with every single number
Select a random index I between 0 and X, and get its value
Move X value into I position
Decrease X and repeat
You should only call srand once in your code and you should call it with a "random" seed like time(NULL).
By calling srand within the loop, and calling it with a 0 seed each time, you'll get six numbers exactly the same.
However, even with those fixes, rand()%50 may give you the same number twice. What you should be using is a shuffle algorithm like this one since it works exactly the same as the lottery machines.
Here's a complete program showing that in action:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static void getSix (int *dst) {
int sz, pos, i, src[50];
for (i = 0; i < sizeof(src)/sizeof(*src); i++)
src[i] = i + 1;
sz = 50;
for (i = 0; i < 6; i++) {
pos = rand() % sz;
dst[i] = src[pos];
src[pos] = src[sz-1];
sz--;
}
}
int main (void) {
srand (time (NULL));
int i, numbers[6];
getSix (numbers);
printf ("Numbers are:\n");
for (i = 0; i < sizeof(numbers)/sizeof(*numbers); i++)
printf (" %d\n", numbers[i]);
return 0;
}
Sample runs:
Numbers are:
25
10
26
4
18
1
Numbers are:
39
45
8
18
17
22
Numbers are:
8
6
49
21
40
28
Numbers are:
37
49
45
43
6
40
I would recommend using a better random number generation algorithm that can offer that internally, rather than using rand.
The problem with rand() and trying to prevent repeats is that finding an unused number will slow down with every number added to the used list, eventually becoming a very long process of finding and discarding numbers.
If you were to use a more complex pseudo-random number generator (and there are many, many available, check Boost for a few), you'll have an easier time and may be able to avoid the repeats altogether. It depends on the algorithm, so you'll need to check the documentation.
To do it without using any additional libraries, you could prefill a vector or list with sequential (or even random) numbers, making sure each number is present once in the list. Then, to generate a number, generate a random number and select (and remove) that item from the list. By removing each item as it's used, so long as every item was present once to begin with, you'll never run into a duplicate.
And if you have access to C++0x you can use the new random generator facilities that wrap all of this junk for you!
http://www2.research.att.com/~bs/C++0xFAQ.html#std-random