An exercise is to write a program that generates random numbers within user specified limits. The program I wrote is as follows and it runs correctly.

#include "../../std_lib_facilities.h"

void randnum(double lower, double upper, int n)  // Generate 'n' random numbers uniformly distributed 
{	                                         // between lower and upper limits.
	double a = 0;
	double b = 0;

	srand((unsigned)time(0));

	for (int i = 1; i < n+1; ++i) {
		a = rand();
		b = lower + (a / 32767) * (upper - lower);   // RAND_MAX for MS VC++ Express is 32,767.
		cout << i <<"  " << b <<endl;
	}
}

int main () 
{
    int z = 0;
    double l = 0;
    double u = 0;

    cout <<"Enter the lower and upper limits for, and the number of random numbers \nto be generated, separated by a space.\n";
    cin >> l >> u >> z;

    randnum(l,u,z);

    keep_window_open();
    return 0;
}

It occurred to me that this only generates numbers uniformly over the range. I have used random number generators that use different probability distributions to generate the numbers. There is uniform, normal, Poisson, binomial, etc. I looked for probability distributions in C++, but found more questions than answers, The math.h header doesn't seem to support any probability functions.

If I want to generate numbers that follow the normal distribution, do I first have to write a function that estimates the normal probability density myself?
(I have done that in Javascript so I think I can do it in C++ as well, but just asking.)

Recommended Answers

All 5 Replies

void randnum(double lower, double upper, int n)  // Generate 'n' random numbers uniformly distributed 
{	                                         // between lower and upper limits.
	double a = 0;
	double b = 0;

	srand((unsigned)time(0));

	for (int i = 1; i < n+1; ++i) {
		a = rand();
		b = lower + (a / 32767) * (upper - lower);   // RAND_MAX for MS VC++ Express is 32,767.
		cout << i <<"  " << b <<endl;
	}
}

You need to be very careful with this code. The random number generator should not be seeded more than once in a single program. The time() function returns an unsigned long integer number representing time since the epochs in seconds. If you made two subsequent calls to the randnum() function within the same second, the function would return two identical values.

The problem of producing random numbers with different distributions is solved in two ways. First, you can go and get a library that already has it implemented. Second, you can implement it yourself.

I have created my own RNG class in the past to solve this problem. This can answer the seeding problem in two ways. First, you can make your RNG class a singleton and call srand() in its constructor. I don't prefer this method because singleton classes are not a native concept in c++. I usually lean toward adding a static boolean flag to the RNG class called isSeeded, or some such. Then, in the constructor of the class, you have it check the isSeeded flag, and if the isSeeded flag is not yet set, the class calls srand() and sets the flag:

class RNG
{
private:
    static bool isSeeded;

public:
    RNG()
    {
        if( !isSeeded )
        {
            srand( time(0) );
            isSeeded = true;
        }
    }
}

bool RNG::isSeeded = false;

>>It occurred to me that this only generates numbers uniformly over the range

In fact, it dosen't. The only way rand() generate uniform distribution is by using the
value it returns as the random number and not manipulate that random number. Thus
when you do something like this : int power = rand()/(RAND_MAX) * (max-min)
you are affecting the distribution. See here for more details.

Also here (a / 32767) * (upper - lower); // RAND_MAX for MS VC++ Express is 32,767.

Instead of saying 32767 is RANDMAX in vc++, just use RANDMAX as the constant. Not
only that will make it clearer, it will be easier to maintain, since say for some reason RAND_MAX was something else later on for whatever reason, now your gonna have
to relocate all usage of 32767 and change it as well. If you want a better distribution then you will have to look at other libraries. rand() usually is good enough for most of your applications, but when you get serious, then you will want to
look at other libraries that have been throughly tested. And forget about creating your own RNG. There is no point.

Thanks for the suggestions. I took a look at Boost.org. Right now most of their stuff is beyond my understanding. But I am glad I know it exists!

Thank you for the heads-up on srand(). I now see the difference in calling it each time the function is called, as I have it now, and each time the program is run.

@dusk,
I am now reading chapter 9 of Stroustrup's book which covers classes, members, constructors, enumerations, etc. I like your suggestion for RNG, it fits in perfectly with what Stroustrup teaches.

@first,
You are right about RAND_MAX. I wrote it the way I did to avoid problems. I tried to write that line with everything as in

b = lower + (rand() / RAND_MAX) * (upper - lower);

It compiled and ran but the output was zeros for all the generated random numbers. After I separated the rand functions/variables from that line, it yielded the correct output. I am much more hyped about getting a program to run correctly than elegantly. When I get good and can write correctly running programs with ease, I will pay more attention to elegance, maintenance, and that stuff.

>>ran but the output was zeros for all the generated random numbers

Thats because rand()/RAND_MAX yields 0 because of integer division. You need to
promote it to this : rand() / float(RAND_MAX)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.