I am in a coding environment where I only have access to some most basic c functions. #include\'ing other lib is not feasible.
In this environment, I can call rand()
rnum = (rand() << 15) | rand()
might be faster, but if you need good quality random numbers you should look for an external library. Built-in random functions are generally adequate only for the simplest applications.
static unsigned long next = 1;
int my_rand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % (RAND_MAX+1));
}
void my_srand(unsigned int seed) {
next = seed;
}
on linux
#define RAND_MAX 2147483647
your environment RAND_MAX is probably 32767
reference: http://en.wikipedia.org/wiki/Linear_congruential_generator
if you are not memory constrained you can look also at http://en.wikipedia.org/wiki/Mersenne_twister the code is embeddable as like as the example above
Before using ANY random number generator for a non-trivial use, it should be tested extensively. Here is a link to one article on this subject.
A fun background on the weaknesses of even true random numbers is available in the various histories on the code-breakers at Bletchley Park in WWII. The Germans and Hitler for most of the war assumed their codes were unbreakable because of being encrypted with random numbers, whereas the British were breaking all of these codes completely within months because of various weaknesses in the German implementation of "randomness". Many codes were sufficiently "twisted", if not outright broken, within a few days or months, sufficiently to be of use even though not completely broken.
Besides the other excellent solutions proposed here, you can also do a power expansion in RAND_MAX, truncate at a user defined MY_RAND_MAX, and discard solutions which would cause uniformity to be destroyed.
int myrand(int MY_RAND_MAX)
{
int j = 0, num = 0;
// Generate digits for expansion in powers of RAND_MAX, up to acceptable range.
while (pow(RAND_MAX + 1, j) <= MY_RAND_MAX){
num = num + rand() * (int)pow(RAND_MAX + 1, j);
j++;
}
//compute remainder to determine truncation
int remainder = ((int)pow(RAND_MAX + 1, j)) % (MY_RAND_MAX + 1);
// If number is within accepted bounds, mod and return
if (num <= ( (int)pow(RAND_MAX + 1, j) - remainder ) ){
return (num % (MY_RAND_MAX + 1));
// Else, if number generated exceeds allowed bounds, rerun method.
}else if (num > ( (int)pow(RAND_MAX + 1, j) - remainder ) ){
return myrand(MY_RAND_MAX);
}else{
exit(-1);
}
}
You can check empirically that this method gives you a statistically uniform output in the given range.
I've done so for several trials with different ranges, each with a sample size of 100000, and got an agreement between the variance of the sample and the expected variance to at least 3 sig. fig.s each time.
p.s. I am not a coder, but a mathematician/physicist who has recently learnt to code, so any and all feedback on the quality of my code would be appreciated.