Sunday 20 November 2011

How do you create random numbers? in C programming

How do you create random numbers?

Well, actually, there’s no such thing as a truly random number generator on a computer. However, a point can be reached where the number repetition pattern is so large that the number appears to be random. That is the ultimate goal of a random number generator. Such a device is called a pseudo-random number generator.

There is a lot of theory about how to generate random numbers. I will not discuss in this section the theory and mathematics behind creating random number generators. Entire books have been written dealing with this subject alone. What can be said about any random number generator is that no matter which implementation you use, you must provide the algorithm some value to get it “started.” It helps if this number is also random, or at least pseudo-random. Fast counting registers or shift registers are often used to create this initial number, called a seed, that is fed into the generator.

For this book, I will demonstrate the use of the random number generator provided by the C language. Modern C compilers include a pseudo-random number generator function to help you produce a random number, based on an ANSI standard. Both Microsoft and Borland support this standard via the rand() and srand() functions. Here’s how they work: You provide the seed for the srand() function; this seed is an unsigned int, so the range is 0 to 65,535. After you have fed the seed to srand(), you call rand(), which returns a random number (in the range of 0 to 32,767) based on the seed value provided to srand(). You can call rand() as many times as you want after seeding srand(), and you’ll continue to get back random numbers. You can, at any time, seed srand() with a different value to further “randomize” the output of

rand().

This process sounds simple enough. The problem is that if you feed srand() the same seed value each time you call it, you will get back the same series of “random” numbers. For example, you call srand() with a seed value of 17. When you call rand(), you get the random number 94. Call rand() again, and you get 26,602. Call rand() a third time, and you get 30,017. Seems fairly random (although this is a painfully small set of data points). If, however, you call srand() again, seeding it with 17 again, rand() will return 94, 26,602, and 30,017 on its first three calls, along with all the remaining numbers you got back in the first series of calls to rand(). Therefore, you still need to seed srand() with a random number so that it can produce a random number. The following example shows a simple, but quite effective, method for generating a fairly random seed  value—the time of day.

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/timeb.h>
void main( void )
{
int i;
unsigned int seedVal;
struct _timeb timeBuf;
_ftime(&timeBuf);
seedVal = ((((((unsigned int)timeBuf.time & 0xFFFF) +
(unsigned int)timeBuf.millitm)) ^
(unsigned int)timeBuf.millitm));
srand((unsigned int)seedVal);
for(i = 0; i < 10; ++i)
printf(“%6d\n”, rand());
}

The function calls _ftime() to retrieve the current time of day in seconds elapsed since January 1, 1970 (no kidding), placed into the timeBuf.time structure member. After the call, the timeBuf structure also contains the number of milliseconds that have elapsed in the current second in the millitm member. Note that in DOS, millitm actually holds the number of hundredths of a second that have elapsed in the current second. The number of milliseconds is added to the elapsed time in seconds, and the total is XORed with the millisecond count. You could apply many more logical mathematical functions to these two structure members to control the range of seedVal and further its apparent randomness, but this example is sufficient.

Note that in the preceding example, the output of rand() has not been scaled to a specific range. Suppose that you want to pretend to create a lottery number-picking machine whose values ranged from 1 to 44. You could simply ignore any output from rand() that did not fall into this range, but it could take a long time before you acquired the necessary six lottery numbers. Instead, you can scale the output from rand() to any numeric range you want. Assume that you have produced a satisfactory random number generator that provides a random number in the range of 0 to 32,767 (as in the case of the earlier example) and that you want to scale the output down to 1 to 44. The following example shows how to accomplish this task:

int i, k, range;
int min, max;
double j;
min = 1; /* 1 is the minimum number allowed */
max = 44; /* 44 is the maximum number allowed */
range = max - min; /* r is the range allowed: 1 to 44 */
i = rand(); /* use the above example in this slot */
/* Normalize the rand() output (scale to 0 to 1) */
/* RAND_MAX is defined in stdlib.h */
j = ((double)i / (double)RAND_MAX);
/* Scale the output to 1 to 44 */
i = (int)(j * (double)range);
i += min;
This example places a restriction on the random output to a range from 1 to 44. Here’s what the function does: It gets a random number whose range is from 0 to RAND_MAX (32,767) and divides that random number by RAND_MAX. This process produces a normalized value—that is, a value whose range is 0 to 1. Next, the normalized value is scaled up by the range of allowed values (43 in this case—44 minus 1). This produces a value from 0 to 43. Next, the minimum amount allowed is added to this number to place the scaled value in the proper range—1 to 44. To experiment, replace the min and max numbers with different values, and you’ll see that the example properly scales the random number to the new min and max values.

Cross Reference:

None.

No comments:

Post a Comment