Simple random number generator in C isn't working - c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char** argv) {
srand(time(NULL));
int r = rand();
printf("%d\n", r);
return (EXIT_SUCCESS);
}
When I run this code snippet repeatedly in the space of a few seconds, I get an increasing series of number such as 213252683, 213975384, 214193875, 214445980. It looks to me like I'm just printing out the system time - that hypothesis seems to be confirmed when I add the line printf("%d\n", time(NULL)); to the code. What am I doing wrong? I'm running on Mac OS X 10.6.1 (Snow Leopard), but I'm only using Standard Library functions, so it shouldn't make a difference. Thanks!

Pseudorandom numbers are generated as a chaotic sequence derived from an initial seed. srand initializes the randomness by setting this seed. Apparently, the first random number in the sequence is the seed itself - which is the time() value you set.
This is the reason, why the right way to generate a random sequence is to call srand() only once at the beginning of the program, and then only call rand() (well, maybe until the sequence starts looping, which shouldn't happen too soon, but that depends on the generating function). Calling srand() too often will, as you have seen, deteriorate the randomness.

The random number generator differs widely, so this will be difficult to reproduce on other machines. It looks like the first number from your implementation is just the seed value. On mine, for example, the first number appears to be linearly related to the seed. Generally, you will call srand once in a program, and rand many times, and successive calls will get more random-looking results. If you want to avoid this problem, it would be reasonable to do:
srand(time(NULL));
rand();
int r = rand();
printf("%d\n", r);
The first rand call makes sure the seed doesn't get returned, and the next one should pick up something that appears more random. Note that if you run the program twice in a short enough time span (such that time(NULL) is the same in both runs) you will get exactly the same results. This is definitely to be expected - use a different seed value (pid + time might be a good start, or just a higher-resolution time) if this is a problem.

When I run this code snippet repeatedly in the space of a few seconds,
I get an increasing series of number such as 213252683, 213975384,
214193875, 214445980.
I cannot reproduce this. On my system (Debian Linux) I get numbers that are not ordered. Also, the results are not the same as what you get when you print time(NULL).
This is as it should be: You are seeding the random number generator with the current time (in seconds). Thus as long as the time (down to seconds) is the same, your program will print the same result.
What am I doing wrong?
Well, that depends on what you want. If you want random numbers for every run, you need a better source of randomness. You could try functions like gettimeofday, which have higher resolution (typically ms, I believe). Also, mix in other sources of randomness, like the ID of your process.
In most programs, the effect you see is no problem, because typically srand() is only called at the start, and then rand() returns a different number on every call.
If you want "secure" (i.e. unpredictable) random numbers, that's a whole other game. See e.g. Wikipedia for an overview.

In case it helps I generally use it that way:
int rand_between(int min, int max)
{
static int flag = 1;
FILE *urandom;
unsigned int seed;
if (flag)
{
flag = 0;
if (!(urandom = fopen ("/dev/urandom", "r")))
fprintf(stderr, "Cannot open /dev/urandom!\n");
fread(&seed, sizeof(seed), 1, urandom);
srand(seed);
}
return ((int)rand() % (max - min)) + min;
}
To get a random uppercase letter:
char letter = (char)rand_between('A', 'Z');

You should use random() instead of rand(). It is superior to rand() in every way, and it is also included in stdlib.
Try the following code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int r = random();
printf("%d\n", r);
return (EXIT_SUCCESS);
}

Related

Why does the first random value just increase every time I run the code?

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[]) {
srand((unsigned)time(NULL));
printf("%d\n", rand()%100+1);
printf("%d", rand()%100+1);
return 0;
}
I've run this many times and each time the first value just increased steadily, like 2 5 9 17 24 30 ..... 91 97 3 7 12 (but the value is always different). Strangely, the second value performed normally, what could be the reason?
I'm using Dev-C++ and TDM-GCC 4.9.2
You're pretty much right, I also don't know the exact or correct reason of this happening.
But I fixed this issue with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
int main(int argc, char *argv[])
{
srand(time(NULL));
for (;;) // running infinitely here until program's interrupted
{
printf("%d\n", rand() % 100 + 1);
printf("%d", rand() % 100 + 1);
printf("\n---\n");
sleep(1);
}
return 0;
}
If you put srand(time(NULL)) outside the infinite loop and everything else inside it, it'll work correctly. After this, you'll get both values changed randomly in each iteration rather than just increasing (the first value).
Your root cause is likely that C's old random number generator is not really that good. In my mind it's primary use cases are when quality is not important or you need the ability to repeat "random number" series to assure test results, and the like, can compare well over time. These "pseudo random number generators" have forever been a sore spot to projects needing good random numbers.
If you need true good stuff you can obtain random numbers using:
Entropy based features found on most popular operating systems, like the /dev/urandom family of random devices on unix-like systems. Microsoft Windows has something as well but I've forgotten it.
Internet random number services like random.org (obviously not for high-volume numbers). They have APIs so programs can automate the experience, which would be educational but be sure to follow the guidelines.
Hardware random number generators (search for: usb random numbers) if you really want quality or quantity.
Historically using just the low-order bits of rand() values tends to amplify the defects, which may help get what you saw. I've posted a second answer that goes into the nuts and bolts of improving on the performance of rand().
Try run
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[]) {
unsigned i;
for (i=0; i<100; ++i) {
srand(i);
printf("%d\n", rand()%100);
}
return 0;
}
If you get a pure increasing list, then it's because your randomness returns seed at the first run.
To fix it, call a rand() just after srand and ignore its value. It'll somehow seem to improve the randomness.
On top of the defective nature of most rand() implementations mentioned in my first answer on broader issues of random numbers there is also a subtle problem in your %100. As RAND_MAX is usually a power of two, say 32767, using just the last two digits will slightly favor lower values as there will be the potential of missing 68-99 some some calls. To get uniform 00-99 distributions you would need to go to 32799, which is not going to happen.
A better solution would be to do something to get a random value from 0.0 to 0.999999... in a way that uses all bits and then expand on that:
//untested code alert:
double rand01 = (double)(rand()%RAND_MAX) / (double)RAND_MAX; // get zero up to but not including one
printf( "%d\n", 1 + int(100.0 * rand01) );
This uses all the available bits in the returned random numbers.
Software generated random numbers have always been a pain-point in computers.

rand() function in C is not random even when seeded

This is most likely a machine dependent issue but I can't figure out what could be wrong.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char** argv) {
srand(time(NULL));
int r1 = rand();
int r2 = rand();
printf("%d %d\n", r1, r2);
}
I compile the above piece of code using
gcc randd.c
Then running it a few times manually and the first numbers seem incredibly similar while the second ones seem random:
1025720610 1435057801
1025737417 1717533050
1025754224 2000008299
1025771031 134999901
1025787838 417475150
This first call to rand() seems strongly co-related to the time and is strictly increasing as time passes. Any ideas as to why this occurs or how to resolve it?
This happens on OSX 10.11
rand() is quite bad, avoid it if possible. In any good RNG the first values will be indistinguishable from random even when the seed is close (hamming distance). In rand this is not the case.
If you must use rand then seed it, preferably with something higher entropy than time, and call rand() multiple times instead of reseeding-calling-reseeding.
For example of 2, consider:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char** argv) {
int t=time(NULL);
srand(t);
for(int i=0; i < 10; i++) {
float r = (float)rand()/(float)(RAND_MAX);
printf("%f\n", r);
}
}
With the result:
0.460600
0.310486
0.339473
0.519799
0.258825
0.072276
0.749423
0.552250
0.665374
0.939103
It's still a bad RNG but at least the range is better when you allow it to use the internal state instead of giving it another similar seed.
This is exactly what you should expect. There's no such thing as "a random number". There are only sequences of numbers with a random distribution. The rand() function generates such sequences, but you're not giving it a chance to, because you keep re-seeding it. The first number generated by rand() may very well be just some function of the seed, or the seed itself. Some rand() functions might hash the seed to hide this, but that doesn't really make them any better, because the contract of rand() is to produce a random sequence.
If you need a sequence of random numbers that survives running multiple programs, you'll have to do something like (a) Write a program that calls srand() once, then calls rand() many times, and have your other programs ask for random numbers from that program over IPC; (b) Use something like /dev/urandom; (c) Use something like random.org.

Shuffling an array

What this code is supposed to do is shuffle an array, nonetheless every time I run it on a I get the same "shuffled" array (of course by inputting the same un-shuffled array) I thought the srand(time(NULL)); part was going to make sure of that. If that is not it I don’t know how to make it really shuffle it.
So to sum up I need to know why my code is shuffling the array the same way every time.
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# include <time.h>
int main(){
int n;
int m;
int tmp;
int i;
printf("Please input the number of elements in your array:\n");
scanf("%d", &n);
int baraja[n];
int tempbaraja[n];
for (int i = 0; i < (sizeof(baraja)/sizeof(baraja[0])); i ++){
printf("Please input the %d element of your array:\n",i);
scanf("%d",&baraja[i]);
}
printf("Unshuffled array:\n");
for (i=0;i < n;i++) {
printf(" %d \n",baraja[i]);
}
for (int i = 0; i < n; i ++){
tempbaraja[i] = baraja[i];
}
for (int i = 0; i < n; i ++){
srand(time(NULL));
m = rand() % n;
if (tempbaraja[m] == baraja[m]){
tmp = baraja[m];
baraja[m] = baraja[i];
baraja[i] = tmp;
}else{
}
}
printf("Shuffled array:\n");
for (i=0;i < n;i++) {
printf(" %d \n",baraja[i]);
}
}
You need to move srand(time(NULL)); outside the for loop.
If you see, rand() is a pseudo-random number generator. srand() is used to provide the seed based on which the random number will be generated by rand().
If every time you seed with the same time(NULL) before each call to rand(), each outcome of rand() is going to be the same.
To achieve the desired result, you need to seed the random number generator only once using srand() and later on each call of rand(), it will give you the random numbers.
Note: Though it is not mandatory, it's good practice to have an explicit return 0 at the end of main().
Get srand(time(NULL)) out of the loop.
From srand reference:
Two different initializations with the same seed will generate the
same succession of results in subsequent calls to rand.
So for each iteration you are initializing the random number generator and getting the first item, which is always the same.
You're misusing srand, it should only be called once outside of the loop. These is also a chance that the srand and rand implementations may be particularly bad on the platform you're running on, leading to poor performance if the program is re-executed quickly.
Alright, I'll answer the followup question. Why is srand() in a loop bad?
The rand() function produces a sequence of acceptably random numbers, without needing srand() at all. The problem is that it's a fixed sequence, so every time you run the program, you'll get the same set of "random" numbers.
The goal of srand(time(NULL)) is to pick a starting value different from any previous starting value. The time() function call is only being used to pick a different starting point, with the drawback that the result only changes once per second. Running the program twice in the same second can be a problem with programs launched from a script file or batch job, but usually not when launched from keyboard or mouse events.
So, using srand(time(NULL)) in the loop has one major evil effect. You only get one new random number every wall-clock second.
Even if you had a high-precision timer to sample from, or used:
unsigned counter = time(NULL);
srand(counter++);
..to choose a different starting value, there are still problems. The distribution of random number chosen from sequential starting points is not as "random" as the overall sequence, and may be quite bad for some generators. If you had a source of starting points that was random enough to give good result from srand();rand();, then you probably wouldn't need rand() at all. You could just use those starting values directly!
Finally, srand() slows down your program. Visual C++ in particular has notoriously slow rand() and srand(), and MinGW uses that library too. (The technical issue is due to storing the seed value in thread local storage, which takes over 100 instructions to find on each call.) However, even a statically linked non-thread-safe version involves an extra call and return that you don't need.
Those are the major reasons that I know of for not using srand() in a loop. Most developers would be happy with "it's not necessary".
The glibc srand() manual page, which states: "The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand(). These sequences are repeatable by calling srand() with the same seed value." Specifically your program potentially violated the clause : "..sequences are repeatable by calling srand() with the same seed value." because it could seed rand() more than once per second with the time -- resulting in identical pseudo-random number sequences.

How to write a random generator function without using time functions, static variables or global variables?

How to write a random generator function without using standard C functions like time functions, static variables or global variables?
/* #include <time.h> Don't use time functions. */
/* int seed = 1234; Don't use global variables. */
int generate_random(void)
{
/* static int seed = 1234; Don't use static variables. */
/* return (time() % 100); Don't use time functions. */
}
In other words, this random generator function should not remember the last state.
you can also use srand by
#include<stdlib.h>
srand(getpid());
int num = rand();
This solution meets all your criterion, but it does require the Internet.*
unsigned generate_random () {
FILE *random;
char cmd[512];
unsigned number;
snprintf(cmd, sizeof(cmd),
"wget -qO - "
"'http://www.random.org/integers/"
"?num=1&min=0&max=%u&col=1&base=10&format=plain&rnd=new'",
USHRT_MAX);
random = popen(cmd, "r");
fscanf(random, "%u", &number);
pclose(random);
return number;
}
*That's not really a mark against the algorithm, though, since the Internet is an excellent source of random data. ;-)
Assuming you need to do your own pseudo-random number generator,
you need to remember the state.
If function shouldn't remember last state, you need to pass it as an argument:
int generate_random(int * lastState)
{
// generate next random from lastState
// store state to lastState
// return result
}
int main(void)
{
int lastState = 1234; // seed it
int random = generate_random(&lastState);
}
do
#include <time.h>
#include <stdlib.h>
srand(time(NULL));
int r = rand();
if you want to limit the number use
int r = minNum + rand() % maxNum;
do not try to create your own random function. it will not end well
Guessing about your question...I have to ask what is the requirement for wanting a random seed?
Being able to set the seed value is a plus for code because you at least try to do things like regression testing.
If your question is about random numbers in general. There are two steps needed to generate a series of random numbers.
First, set a seed value, for example, srand(1234); where 1234 is the seed value. Your code only issues this instruction once. When you run the program a second time your code can re-use the same seed value, in which case the sequence of random numbers will be the same. If you set a different seed, then you will get a different sequence of random numbers.
The second step is to retrieve the random number values for use in your code.
One Possible Method
In theory, you could use a fixed seed value and then generate R random numbers, where R is some number taken from the system mod 100 (for example). Then use that R'th random number as the seed value for the actual sequence of random numbers for your application.
You say that you don't want to use Time(), but maybe in this double sequence of random numbers and the Time() mod n function will provide enough randomness.
Now, I say in theory, because random numbers from rand() are actually psuedo-random and for all intents and purposes they really are random (guys with math PhDs say this...), so I doubt if doing this "double selection" will make the numbers more random. But, this method or one like it might make a reviewer or boss feel more comfortable, but this would be a false sense of security.

Why isn't this number random?

For the following piece of code:
#include<stdlib.h>
#include<stdio.h>
int main()
{
int x;
x = rand()%100;
printf("The Random Number is: %i", x);
return 0;
}
It always seems to print the random number as 83. Why is this?
Most random number generators are repeatable. You need to seed the generator before using it which you typically do using the system time.
#include <time.h>
srand(time(NULL));
Obligatory XKCD reference:
As people have said, you need to seed the pseudo random number generator properly.
The trouble is, it still only generates pseudo random numbers. Most "true" random number generators require access to some physical phenomenon that is random in nature (for example, clock skews or temperature fluctuations).
Otherwise, the XKCD reference is not too far from the truth. Nor is Dilbert.
Because the pseudo-random number generator used by rand is always initialized with the same seed.
In order to initialize it with a different seed, you can use the srand function, and initialize it as, say, srand(time(NULL)).
Because 83 is a random number, isn't it ?
More seriously, it is useful to have programs providing a repeatable behavior so by default, rand always returns the same sequence of numbers if you don't change the seed.
Seed the random number generator by including <time.h> and calling srand(time(0)); (edited thanks to my commenters)
You can not generate a random number which is truly random until and unless your random number generator has access to a truly random physical phenomenon as quoted earlier by peter. But for a general use you can use C's standard library functions for generating random numbers. Here is a sample code for generating random number between two limits(max and min):
#include<stdio.h>
#include<stdlib.h>
#define MIN 1
#define MAX 5
#define QUANTITY 5
int main()
{
int i;
//stores the time in seconds
time_t seconds;
//getting the system time
time(&seconds);
//initializing the random generator with system time
//as the seed value
srand((long)seconds);
for(i = 0; i < QUANTITY; i++)
{
printf("%f\t",((float)rand())/RAND_MAX*(MAX-MIN)+MIN);
}
printf("\n");
return 0;
}

Resources