**Method for generating random numbers with arbitrary distribution-VC Program Implementation**
Download source code

Abstract:

Random numbers are widely used, such as game design and signal processing. Generally, we can easily obtain random numbers distributed evenly. But how can we generate random numbers with other distributions based on random numbers distributed evenly? In this paper, a method based on geometric intuitive area is proposed. The generation of random numbers with normal distribution is used as an example to discuss the generation of random numbers with arbitrary distribution.

Body:

**I. Generation of evenly distributed random numbers**

As we all know, random numbers play a major role in all aspects. In the VC environment, we provide the library function rand () to generate a random integer. The random number ranges from 0 to 0 on average ~ Rand_max is evenly distributed. rand_max is a constant defined in the vc6.0 environment as follows:

#define RAND_MAX 0x7fff

It is the maximum value of a short type data. To generate a floating-point random number, you can use rand ()/1000.0 To Get A 0 ~ A random floating point number that is evenly distributed between 32.767. If you want to increase the range, you can generate a linear combination of several random numbers to realize random numbers distributed evenly in any range. For example, to generate-1000 ~ The accuracy between 1000 is a random number with an even distribution of four decimal places. Generates a random integer between 0 and 10000. The method is as follows:

int a = rand()%10000;

Then the four decimal places are retained to generate 0 ~ Random decimal number between 1:

double b = (double)a/10000.0;

Then, a linear combination can be used to generate random numbers in any range.-1000 ~ The Random Number of the average distribution within 1000 can be as follows:

double dValue = (rand()%10000)/10000.0*1000-(rand()%10000)/10000.0*1000;

Dvalue is the desired value.

So far, you may think that all the work has been completed. Otherwise, you may find that there is a problem. After simplifying the formula above, it will become:

double dValue = (rand()%10000)/10.0-(rand()%10000)/10.0;

In this way, the range of the generated random number is correct, but the accuracy is incorrect. It turns into a random number with only one correct decimal number, and the decimal number of the last three digits is zero, obviously it's not what we want. Why? What should we do.

Find the cause first. The Random Number Resolution produced by rand () is 32767, and the two are 65534. After the remainder, the degree of parallelism is reduced to 10000, the two are 20000 and the required resolution is 1000*10000*2 = 20000000, which is obviously far from enough. The methods provided below can achieve the correct results:

double a = (rand()%10000) * (rand()%1000)/10000.0;

double b = (rand()%10000) * (rand()%1000)/10000.0;

double dValue = a-b;

Dvalue is the required result. In the following function, you can generate a random number with an average distribution within a range with a precision of 4 decimal places.

double AverageRandom(double min,double max)

{

int minInteger = (int)(min*10000);

int maxInteger = (int)(max*10000);

int randInteger = rand()*rand();

int diffInteger = maxInteger - minInteger;

int resultInteger = randInteger % diffInteger + minInteger;

return resultInteger/10000.0;

}

However, there is a noteworthy problem that the generation of random numbers requires a Random Seed, because the random numbers produced by computers are obtained through recursive methods and must have an initial value, that is to say, the host-on-demand seed. If Random Seed is not initialized, the computer will have a random seed that is indeed saved, so that the results of each recurrence will be exactly the same, therefore, we need to initialize the Random Seed every time the program runs. In VC, the method is to call the srand (INT) function. Its parameter is a random seed, but if a constant is given, the obtained random sequence is exactly the same, so the system time can be used as the Random Seed, because the system time can ensure its randomness.

The call method is srand (gettickcount (), but srand (gettickcount () cannot be used to initialize each call to Rand (), because the computer is running fast now, when rand () is called consecutively, the system time is not updated, so the Random Seed obtained is exactly the same for a period of time, therefore, Random Seed Initialization is generally performed only once before a large number of random numbers are generated. The following code generates 400 in-1 ~ A random number that is evenly distributed between 1.

double dValue[400];

srand(GetTickCount());

for(int i= 0;i < 400; i++)

{

double dValue[i] = AverageRandom(-1,1);

}

The random number generated by this method is shown in result 1:

Figure 1 400-1 ~ Random Number with an average distribution between 1

**Ii. Generation of random numbers distributed randomly**

The following describes how to generate random numbers with known probability density functions. A typical normal distribution is used as an example to generate random numbers with arbitrary names.

If a random number sequence follows a one-dimensional normal distribution, it has the following probability density functions:

(1-1)

Where μ, σ (> 0) are constants, which are mathematical expectations and mean variance. If you are not clear about the concepts of mathematical expectations and mean variance, please refer to relevant probability theory books. If μ = 0, σ = 0.2, the curve is

Figure 2 probability density function curve of Normal Distribution

We can see that the probability density near μs is large, and the probability density away from μs is small. The random numbers we want to generate must follow this distribution, this means that the probability of the random number to be generated near μs should be large and smaller than μs. The following method can be used to ensure this: points are randomly generated in the large rectangle in Figure 2. These points are evenly distributed. If the generated points fall below the probability density curve, the generated points are considered to meet the requirements, keep them. If they are above the probability density curve, they are considered unqualified and placed. If a large number of points are randomly distributed evenly in the entire rectangle, the abscissa of the points to be preserved follows the normal distribution. It can be imagined that, because the f (x) value at μ is relatively large, the number of points near μ is naturally large, and the number of points close to μ is small, this can be seen from the area. The random number we want to generate is the abscissa here.

Based on the above idea, we can use a program to implement a random number that follows a normal distribution within a certain range. The procedure is as follows:

Double normal (Double X, double Miu, double sigma) // probability density function

{

Return 1.0/SQRT (2 * pI * sigma) * exp (-1*(X-Miu)/(2 * Sigma * sigma ));

}

Double normalrandom (double Miu,

Double Sigma, double min, double max) // generates a random number with a normal distribution

{

Double X;

Double dscope;

Double Y;

Do

{

X = averagerandom (Min, max );

Y = normal (dresult, Miu, SIGMA );

Dsdom = averagerandom (0, normal (Miu, Miu, SIGMA ));

} While (dscope> Y );

Return X;

}

Parameter description: Double Miu: μ, mathematical expectation of a normal function

Double Sigma: σ, mean variance of Normal Functions

Double min, double Max, indicating the range of the generated Random Number

In the above method, take μ = 0, σ = 0.2, And the range is-1 ~ 1 to generate 400 normal random numbers 3 is shown in:

Figure 3 μ = 0, σ = 0.2, range:-1 ~ Random Number Distribution of 400 normal distributions at 1 hour

Take μ = 0, σ = 0.05, range:-1 ~ 1 to generate 400 normal random numbers 4 is shown in:

Figure 4 μ = 0, σ = 0.05, range:-1 ~ Random Number Distribution of 400 normal distributions at 1 hour

From the comparison in figure 3 and figure 4, we can see that the smaller the number, the more random numbers are generated, and the higher the probability of a random number approaching.

We first generate 4000 random numbers with a normal distribution between 0 and 4, take μ = 0, σ = 0.2, and then make statistics on the number of generated data and draw a curve, as shown in figure 5:

Figure 5 μ = 0, σ = 0.2, range: 0 ~ Random Number statistics of 4000 normal distributions

As you can see from Figure 5, there are a large number of records generated at the same distance, and the number of records generated at the same distance is small. The contour line of the chart exactly matches the shape of the probability density curve. This verifies the correctness of the method.

With the above foundation, the same method is used. As long as you know the probability density function, it is not difficult to generate random numbers with any distribution. The method generates a vertex first and then makes a trade-off, the point falling below the probability density curve meets the requirements. The abscissa is the random number to be obtained.

References:

1. Publishing House of higher education, "probability theory and mathematical statistics", Sheng Shi, Xie Shiqian, etc.

2. System Simulation Technology and Application Based on Matlab/Simulink Tsinghua University Press, Xue dingyu, Chen Yangquan

Latest comment [Post comment] [Article Contribution] |
View All comments and recommend them to friends |

A completely incorrect algorithm. If rand () is a random number that is evenly distributed between 0 and 32767, Rand () * rand () is not evenly distributed. What's more, Rand () Only simulates random numbers using the linear same-remainder method.

You can only use this algorithm to generate a random number with four decimal places, but it is far from the average distribution (bloodywind was published at 19:00:00)

I believe this post is useful to us. However, it is not clear that the time is tight.

As the landlord said: "random numbers are evenly distributed in any range. For example, to generate-1000 ~ The accuracy between 1000 is a random number with an even distribution of four decimal places. Generates a random integer between 0 and 10000. The method is as follows:

Int A = rand () % 10000 ;"

In my opinion, the obtained a is not a random number distributed evenly between 0 and 10000, but the input of a as the random number of the evenly distributed data is problematic.

Since rand () gets a 0 ~ The number of evenly distributed data between 32767, so it is easy to prove that the value of a belongs to 0 ~ 2767 and 2768 ~ The ratio of the 9999 frequency should be 4: 3. That is, P (0 ~ 2767): p (2768 ~ 9999) = 4: 3.

So int A = rand () % 10000; I think it should be changed:

// <--------------------

Int A, B;

Do {

B = rand ();

} While (B> 29999); // returns a value greater than 29999.

A = B % 10000;

// -------------------->

Tasbbon@gmail.com

Http://gkbc.bokee.com

Reply to me.

(Tasbbon was published at 15:12:00)

Y = normal (dresult, Miu, SIGMA );

The dresult in should indeed be X, which is the author's negligence. Thank you for pointing out. The formula should be

Return 1.0/(SQRT (2 * PI) * sigma)

* Exp (-1*(X-Miu)/(2 * Sigma * sigma ));

Therefore, the formula (1-1) is incorrect.

(Bsrong was published on 19:09:00)

First of all, I would like to thank the author for providing us with such a valuable algorithm. Thank you. I am not very clear about the meaning of dresult, But I later used VB to compile a normal random algorithm. I personally think this dresult should be X and I don't know if it is correct .. Thank you .. (Xz403 posted on 20:57:00)

What does dresult in this article mean?

(Seeyour was published on 16:57:00)

The original formula is indeed wrong. You are correct (pipipipi was published at 23:45:00)

Is the one-dimensional normal probability density function formula in your program incorrect? It should be return 1.0/(SQRT (2 * PI) * sigma)

* Exp (-1*(X-Miu)/(2 * Sigma * sigma ));

I suggest you write it like that on your own. The younger brother is not clear. (songzhiguan1981 was published on 13:33:00)

========================================================== ==============