This question already has answers here:
srand() — why call it only once?
(7 answers)
Closed 4 years ago.
I'm trying to generate 10,000 random numbers in a row in C and am having trouble getting random or even randomish results using the pseudo RNG. I used modulus in a way that I think should create uniformity, which it does, but the results are equivalent to 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3 etc. when run in a loop in another function calling RNG(4).
int RNG(int n) {
int range = RAND_MAX - (RAND_MAX % n);
srand(time(NULL));
int x = rand();
while (x > range) {
x = rand();
}
return x % n;
}
Any way to get it closer to 1,3,2,0,2,3,1,0,0,3,2,0,1 etc. would be appreciated!
Thank you!
EDIT: Thanks for the responses everyone! Moved the seeding to the start of the function calling RNG and everything is dandy now!
Do not call srand every time you want to generate a number. srand initializes the pseudo-random number generator and is intended to be called just once at the start of your program, or when you want to reset the generator. By resetting it every time, you are forcing rand to generate the same numbers every time you call it within each second on the clock.
Do not use x % n to reduce the number to a desired range. Old implementations of rand are notoriously bad and have patterns in the low bits. Instead, use x / ((RAND_MAX+1u) / n).
The code int range = RAND_MAX - (RAND_MAX % n); is flawed. Suppose n is 4 and RAND_MAX is 7, meaning rand returns 0 to 7. This code sets range to 4, and then while (x > range) x = rand(); discards 5, 6, and 7, while it retains 4. There are two bugs here: The code keeps the five values 0, 1, 2, 3, and 4, which is a mismatch to (not a multiple of) the desired range of 4, and it unnecessarily discards values. If we had kept 4, 5, 6, and 7, we would have a match. You could use:
unsigned range = (RAND_MAX + 1u) - ((RAND_MAX + 1u) % n);
and:
while (x >= range) x = rand();
If you are using C++, switch to using std::uniform_int_distribution. If you are using C, check the quality of rand in your implementation or switch to another generator such as the POSIX srandom and random.
As noted elsewhere, the fix to the repeated numbers is to move the call to srand(time(NULL)) outside this function and call it only once per program at the beginning.
As for why you're getting repeated numbers: The function is being called several times per second. Each time the function executes in a given second, time(NULL) returns the same number, which this code uses to seed the random number generator.
The sequence of random numbers generated from a particular seed will always be the same. This code takes the first number from that sequence, which is always the same for one second, until time(NULL) returns a new value.
Sorry, I know there are similar questions already posted but this book is confusing me nonetheless.
In "C Programming: Absolute Beginner's Guide", there is a line:
dice1 = (rand() % 5) + 1;
to generate a random number between 1 to 6 for a dice game.
Isn't this an error? From my understanding, you cannot get a remainder of 5 using % 5 so that line would only generate numbers from 1 to 5. I'm an absolute beginner so I can't tell if I'm making an error or the book is. Could someone confirm?
Yes, 5 % 5 == 0, so you could only get numbers 1 to 5 from the full expression. The other issue with that method is that rand() probably returns numbers from 0 to 2n-1, so the total number of different values can only be divided equally to some other power of two.
So the modulus doesn't give an even distribution of the resulting numbers, even assuming rand() itself gives evenly distributed values along its output range.
This question already has answers here:
What is the optimal algorithm for generating an unbiased random integer within a range?
(7 answers)
How to generate a random int in C?
(32 answers)
Closed 7 years ago.
I want to create some specific random, such that from 10 to 20.
rand()%20;
is create from 0 to 19
Apply some simple arithmetic
int val = min + (rand() % range);
Where range is (max - min) + 1
A random number betweeen 10-20 is just a random number between 0-10 shifted +10
This question already has answers here:
How to generate a random integer number from within a range
(11 answers)
Closed 8 years ago.
I would like to generate random numbers between 1 and 25 with the method rand().
But I only know how to generate random numbers this way, which includes the number zero by default:
int r = rand() % 26 /* random int between 0 and 25 */
Anyone? Thank you.
Very simple
int r = 1 + rand() % 25 /* random int between 1 and 25 */
but you should use this
int r = (int)(1.0 + 25.0 * rand() / RAND_MAX)
as mentioned in the comments, the second is the more robust way to generate random numbers see this link
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to generate a random float between 0 and 1?
I want to generate a random number between 0 and 1 (uniform distribution) and I use:
float x = arc4random_uniform(1);
However, this produces only 0.00000
I used
float y = arc4random() %11 * 0.1;
which returns a random number in the interval but I am not sure if it is uniform distribution.
Why isn't the first function working as expected?
I use:
float x = arc4random_uniform(1);
However, this produces only 0.00000
Of course it does. arc4random_uniform() returns a 32-bit unsigned integer. It does not return a float. What you're looking for is something like
#define RAND_PRECISION 1024
float x = arc4random_uniform(RAND_PRECISION) / (float)RAND_PRECISION;
Also,
I am not sure if it is uniform distribution.
Since it isn't. Using the modulo (%) operator results in a non-uniform distribution.
According to the documentation, arc4random_uniform returns an integer, so using it with an upper bound of 1 won't produce what you want.
Here's the page on the arc4random functions:
http://www.unix.com/man-page/FreeBSD/3/arc4random_uniform/
#define ARC4RANDOM_MAX 0x100000000
...
double val = ((double)arc4random() / ARC4RANDOM_MAX);
arc4random_uniform returns a number up to the upper bound you provide (e.g. arc4random_uniform(10) will return a number between 0 and 9). Due to that arc4random_uniform(1) should always return 0 (which is what you're seeing). If you want a random float you should see this answer:
Generate a random float between 0 and 1