C Programming - bizarre output from rand()
Below is a sample program I got to practice the use of the rand() function.
The weirdest thing is that every time the program is run, the first number generated by rand() (rand[0] in the program's output) is SIMILAR. It's not the same, but the number is always just slightly larger than the last time it was generated. rand[1-4] seem to be acceptably random however. Can anyone explain what is going on, and why??
Take a look at this sample output:
[paul@experimental C] $ ./a.out
rand[0]= 277735441 <<<??????
rand[1]= 1417591956
rand[2]= 1284424674
rand[3]= 819876274
rand[4]= 1405457966
[paul@experimental C] $ ./a.out
rand[0]= 277769055 <<<???????
rand[1]= 1982542454
rand[2]= 234757526
rand[3]= 642279943
rand[4]= 1546192179
[paul@experimental C] $ ./a.out
rand[0]= 277785862 <<<???????
rand[1]= 117534056
开发者_开发知识库rand[2]= 1857407599
rand[3]= 1627223601
rand[4]= 542817462
The source code:
/*
* rand: Generates 5 numbers using standard "srand()/rand()" function
*
* SAMPLE OUTPUT:
* rand[0]= 824522256
* rand[1]= 1360907941
* rand[2]= 1513675795
* rand[3]= 1046462087
* rand[4]= 253823980
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int
main (int argc, char *argv[])
{
/* Simple "srand()" seed: just use "time()" */
unsigned int iseed = (unsigned int)time(0);
srand (iseed);
/* Now generate 5 pseudo-random numbers */
int i;
for (i=0; i<5; i++)
{
printf ("rand[%d]= %u\n",
i, rand ());
}
return 0;
}
A common implementation of srand
leaves the first random number highly correlated to its seed. The standard makes no guarantees about how random the sequence must be.
rand
returns a signed int. You're printing it as an unsigned value.
Well basically rand() is a pseudo random generator. Since you're seeding using time(), that's probably the reason why the numbers are similar.
Try seeding using gettimeofday() multiplying tv_sec * tv_usec, or something similar.
Pseudo-random generators are never truly random, but based on a wide variety of mathematical algorithms. On my system, apparently a reasonably simple one is used, per the man pages:
static unsigned long next = 1;
/* RAND_MAX assumed to be 32767 */
int myrand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
void mysrand(unsigned seed) {
next = seed;
}
These type of random generators have been around for a while. If you are familiar with remainder arithmetic, then you see that you take a starting value, and twist and turn it with a remainder relative to 32768, and so get a value in the range promised by your machine. Nothing about this though is random. Your value produced is then used as a starting value for your next number.
In your case, you seed with the current time. If you run your program fast enough, you might even get the same value (that shouldn't happen, but it worked for me when I compiled your little program and ran it on my system). In any case, if you have one run fast after the other, you will likely see similar values - until you 'flip over' the remainder base.
Maybe read up on random number generation here:
http://en.wikipedia.org/wiki/Pseudorandom_number_generator
and it will make a little more sense.
Edit: If you wonder how people come up with the constants used to multiply your seed values, the quality of a pseudo-random generator is evaluated based on a number of criteria, such as, are the resulting values 'random looking' or 'clustered'. If you need seriously good pseudo-random numbers (probably not right now), you might want to implement your own.
精彩评论