ZZ pedgoras semi-circle: rand7 is an integer random number that can generate numbers from 1 to 7. Rand7 is required to generate an integer random number ranging from 1 to 10. See the original post. At the LZ prompt, I found a more concise method. For the same cycle method, only one line of code is required! I have discussed several methods in depth and need to learn more. I feel that my knowledge is vast and I am small.

**1. Combined Mathematical Methods**

I have provided this method in my post. This simple algorithm does not seem so easy to understand.

1st times 1 2 3 4 5 6 7 use rand7 to get a number

Take a number from 2, 4, 5, 6, and 8 for 2nd times.

Take a number from 3 4 5 6 7 8 9 3rd Times

Take a number from 4 5 6 7 8 9 10 4th times

Take a number from 5 6 7 8 9 10 1 5th times

Take a number from 6 7 8 9 10 1 2 6th times

...

Take a number from 10 1 2 3 4 5 6 for 10th times

From 1 to 10, each number appears 7 times in the preceding table, with a total of 70 numbers. In this way, the probability of each number being hit is 1/10.

The keyword here is "hit ".

Recycle 11th times, and take a number from 1 2 3 4 5 6 7

Take a number from 2, 4, 5, 6, and 8 for 12th times.

......

In this way, the probability of hit of each number from 1 to 10 is evenly distributed. In essence, an array of 1-10 times generates a rotation structure of all 1-10 in order, that is, all the sequences generated in the problem of combination. (See the art of computer programming, volume4, generating all tuples and permutations in volume 4th of knuth.) after a long period of time, you can see the even distribution. In fact, any random number algorithm requires a long process to observe its distribution. The probability distribution is a statistical concept.

It can be concluded that**Use M random numbers to generate n random numbers**.

1. When M> N, use the rounding method. If n random numbers exceed this range, discard them.

2. when M is less than N, use the above method to create an array of m size, where numbers rotate cyclically from 1 to n, so that after N * m cycles, then we can obtain n even random numbers.

**2. Same remainder cycle method**Mingliang1212 prompts me that the above method is actually equivalent to (rand7 () + I) % 10, I repeats the loop from 0-9, and the remainder of each calculation is exactly equivalent to the above method. That is to say, it is a clever idea to generate all sorts by using the same remainder nature! So: 1. I repeats the loop from 0 to 9

2. (rand7 () + I) % 10, generate a random number of 0-9, equivalent to the first combination method (you only need to change 1-10 in the above table to 0-9)

3. + 1 to obtain a random number ranging from 1 to 10.

After optimization, only one line of code is required! This code is provided at the end of this article.

So the above**Use M random numbers to generate n random numbers**, There is a more concise algorithm, the steps are similar to this will not be written. Feel the power of mathematics! Also, thanks to mingliang1212.

3. Rounding

In most cases, this question won't be taken away, because he is still ordinary. But in fact, the rounding method is also very useful, so it is still written, and the rounding method will be mentioned later.

1. The first time rand7 is used to retrieve a random number ranging from 1 to 5, it is recorded as

2. Take 1 or 2 out of rand7 for the second time and mark it as B.

3. If B = 1, C = A. If B = 2, c = a + B

4. Return C

**4. Combined rand7 computing**

Many netizens, including myself, also used (rand7 () + rand7 () + 7 + rand7 () + 14 + ....) % 10 method class to generate a random number, also want to use rand7 () * rand7 () * rand7 ()..... then perform various computations to generate them. Then I realized that only**Approximate Uniformity**.

From a statistical point of view, the calculation result of N rand7 is the Joint Distribution of n random variables with the same independent distribution (IID), that is, if X1, x2 ,... XN ~ U () (subject to the uniform distribution of 1-7), and the calculated result conforms to F (x1, x2 ,... the Union probability distribution of XN). Now, F (x1, x2 ,... XN) distribution is transformed to U (). If the limit method is not used, it is very difficult. While**In this example, it is impossible**This is because:

1) The rand7 unary operation can have only 7 results, and 10 random numbers cannot be generated.

2) There are currently binary operations (x) that can be addition, subtraction, multiplication, division, or any function ing relationships. rand7 (x) rand7 may be operated in 7*7 ways ,, after N binary (x) operations, the possible calculation method is 7 ^ (n + 1). Now we need 7 ^ (n + 1) it is impossible to obtain 10 results in a uniform operation process (because 7 ^ n cannot be divisible by 10), so it can only be approximately even.

Another hope is to use this method: Call rand7 twice to generate a 7-in-7 number, and then convert it to 0-49, which is the even distribution of 50 numbers, and then take the modulo 10. This method seems to be feasible, but unfortunately, the resulting 7 hexadecimal 0-66 corresponds to 0-48 in the 10 hexadecimal format, rather than 49, with a smaller number.

**5. Distribution of Continuous Random Variables**

Rand7 in this question is a discrete random variable. It only takes an integer from 1 to 7. The disadvantage of discrete variables is that they are inconvenient in mathematical calculation, so they can be converted into continuous random variables. That is, 1-7 continuous and even distribution is generated from rand7 to obtain 1-10 uniform distribution. Although this method is not applicable to this question, this question is useful in addition to exams and will not appear in practical applications. More methods are to change from one distribution to another.

The answer now is very simple. From a geometric point of view, we can map the points on the [a, B] line segments to another line segment [c, d] one by one, only one linear transformation y = (X-A)/(B-a) * (D-C) + C. then, if Rand ()~ U (a, B), then Y = (RAND ()-A)/(B-a) * (D-C) + C ~ U (c, d), that is, if Rand () is an even distribution from A to B, then Y = (D-C) (X-) /(B-A) + C is the uniform distribution from C to D. In this example, rand10 = (RAND ()-1)/6*9 + 1. Below is a proof that, in general, the same can be proved:

Another important theorem is used to indicate the distribution after transformation. This can process multiple transformations such as Y = x ^ 2 and Y = e ^ X. The theorem is as follows:

This theorem can be stronger, and f (x) can be a segmentation or even a coverage (including. Generating Random numbers from random numbers conforming to one distribution is a topic of statistical simulation. There is an interesting transformation method, for example, if X is (0, 1) even Distribution on, y =-A * log (X) is an exponential distribution. For details, refer to statistical inference or further materials.

**6. Let's talk about the rounding method again.**

The rand function in C language may use a linear coordinality algorithm to obtain a uniform distribution. This type of function is called a direct method. On the fifth floor, I also mentioned how to use the transformation to obtain other distributions from the even distribution. These are called direct methods. The rounding method is also a very important type of random, used to generate random numbers of various distributions, such as the Metropolis algorithm and the famous Markov Chain Monte Carlo (MCMC) algorithm, this type of method can be regarded as a black box, requiring that the algorithm quickly converge to a probability distribution through several operations and then return a random number. See Casella & Berger statistical inference (Statistical

Inference) and kunth 2nd volume seminumerical algorithms, random numbers.**7. Code of this question**

// 1. implementation of combined math # include <stdio. h> # include <stdlib. h> # include <memory. h> # include <time. h> static int X [7] = {1, 2, 3, 4, 5, 6, 7}; // rotate the array, initially 1-7 // call once, implement a 1-10 rotation void shift_array () {memcpy (x, x + 1, 6 * sizeof (INT )); X [6] = (* x + 6) % 10; If (! (X [6]) x [6] = 10; // There may be better writing.} // return a random number ranging from 1 to 10. Do not forget to call srand () first () int rand10 () {shift_array (); // returns X [rand () % 7] At a rotation time; // returns a number in the array randomly} void main (void) {unsigned int result [10] = {0}; int K; srand (unsigned INT) time (0); // set the seed for (k = 0; k <100000; k ++) result [rand10 ()-1] ++; For (k = 0; k <10; k ++) printf ("% d: %. 05f \ n ", k + 1, (double) result [k] gloabl_ I/100000);} // 2. the difference between this method and the above method is that different static unsigned int gi = 0; // A = rand () % 7 + 1: generate a random number from 1 to 7 // B = I ++ % 10: I loops from 0-9 // (a + B) % 10, and loops generate a random number of 0-9, for details, see the description of the first method. // This result is plus 1 to generate a random number of 1-10. // do not forget to call srand () int new_rand10 () {return (RAND () % 7 + 1) + (GI ++ % 10) % 10) + 1 ;}