0-1 Probability ProblemProblem description
- A random number generator generates 0 with probability P and 1 with probability (1-p). How to generate equal probability 0 and 1?
Main Ideas
- If two bits are generated using this generator, the probability of occurrence of 00 is P ^ 2, the probability of occurrence of 01 is P (1-p), and the probability of occurrence of 10 is P (1-p ), the probability of 11 is (1-p) ^ 2. Therefore, we can use 10 to represent 1, 01 to represent 0, so as to ensure that the probability of generating 0 and 1 is the same.
Code Implementation
int generate01(int (*func)()) { if (func == NULL) return -1; int num1 = -1; int num2 = -1; int ret = -1; while(num1 != num2){ num1 = func(); num2 = func(); if (num1 == 1 && num2 == 0) { ret = 1; break; } else if (num1 == 0 && num2 == 1) { ret = 0; break; } } return ret;}
0-1 problem Extension
- Use this random number generator to generate equal probability 1, 2 ,......, N
Main Ideas
- Generate a 0-1 generator using the Equi-probability implemented above. The equi-probability generates K binary bits, and the integer x represents 0 ~ Output x + 1 in the n-1 range. Otherwise, the output is repeated.
Code Implementation
int generateRandomNum(int max) { if (max < 1) { return -1; } int bit_num = 0, i = 0; int result = 0; while((0x01 << bit_num) < max) ++bit_num; //while(result > n) { while(bit_num > i) { if (generate01()) result |= 0x01 <<bit_num; //result |= 0x01<<i i++; } i = 0; // } return result;}
Generation of non-repeated random numbers
Problem description
- Randomly generate 0 ~ K non-repeated random numbers in n-1.
Main Ideas
- Borrow the reservoir Algorithm. First define a 1 ~ N-1 array, and then samples K number from it.
Problem description of generating random numbers within a given range
Solution
Number of K generation (k> 1). Assume that the numbers are N1, N2 ,...... NK, then the number of production: N1-1 + (N2-1) * 5 + (N3-1) * 5 ^ 2 ,......, (Nk-1) * 5 ^ (k-1), that is, the generated digit in the (^ (k-1) interval. Then divide the interval into k points, and the generated random number is located (0 ~ 6), and then + 1. If it is in the remainder range of K, the above process is re-executed. (PS: Do not worry about the remainder problem. When k is set to 3, the probability of falling into the remainder range has been reduced to 6/125, and the remainder does not cause the probability problem, but only affects the efficiency. The sub-solution is equivalent to the 5-hexadecimal System)
Code Implementation
int generateRandom(int n) { if (n < 1) return -1; unsigned long long result = 0; for (int i = 0; i < n; i++) { result += rand5(); } result /= 5; return result;}
How to randomly select 1000 keywords
Problem description
- A given data stream contains endless search keywords (for example, keywords that people continuously enter during Google search ). How can we randomly select 1000 keywords from this endless stream?
Main Ideas
- Using the reservoir algorithm. In an array of 1000 characters, the first 1000 keywords are entered in the array, and the subsequent keywords are randomly exchanged.
Randomly select a point from the circle with a radius of 1Main Ideas
- Assume that the center is (0, 0 ). Randomly select a point in a square on the X axis [-] and y axis [-], and then determine whether the point is in the circle. The square area is 4, and the circular area is pi. Therefore, the probability that the random points in the square fall into the circle is: PI/4.
Code Implementation
void generatePoint(double*x, double *y, int r){ int base = 10000; while (pow(*x, 2) + pow(*y, 2) > pow(r, 2)) { *x = random() % 10000; *y = random() % 10000; *x = (2 * r / (*x)) - r; *y = (2 * r / (*y)) - r; }}
Reservoir Algorithm
Problem description
- From the N number, K are randomly selected. Yes, the extraction probability of each number is the same, and the K value is unknown in advance.
Main ideas:
- Keep a set (each number in this set appears) as a reservoir, and replace the number in this reservoir with a certain probability when traversing all data in sequence. Place the first k elements in the reservoir, and then replace the first I element with the probability of K/I.
Proof of method:
- Initial Condition. The probability of occurrence of k elements in the reservoir is the same, all of which are 1.
- Step 1: process the k + 1 element. There are two situations: ① none of the elements are replaced; ② one element is replaced by K + 1.
- For case ②: the probability that the K + 1 element is selected is k/(k + 1 ), therefore, the probability of this new element appearing in the reservoir must be K/(k + 1 ). The probability of the remaining elements in the reservoir is 1-P (P is the probability of element replacement ). The probability that any element in the reservoir is replaced is: (K/k + 1) * (1/K) = 1/(k + 1 ). The probability that the old element appears is k/k + 1. That is, the probability that the old and new elements appear is equal.
- For case ①: when no element is replaced, each element has the same probability. Specific: 1-P (P is the k + 1 element selected) = 1-k/(k + 1) = 1/(k + 1)
- Use induction:
- For the K + I elements, where I (0, length-K ). The probability of its appearance in the reservoir is k/(K + I ). The above two steps can be used to draw a conclusion.
Algorithm Implementation:
int impounding_reservoir(int *array,int length, int k) { if (k <= 0 || array == NULL || length <= 0 || k > length) { return 0; } int result[k]; int i = 0, j = 0; srand((unsigned) time(NULL)); for (i = 0; i < k; i++) { result[i] = array[i]; } for (i = k; i < length; i++) { j = random() % length; if(j < k) result[j] = array[i]; } for (i = 0; i < k; i++) printf("%d ", result[i]); printf("\n"); return k;}
Generate 1 ~ 20 random numbers not repeated in the range of 400
int * generateRandom(int *array, int num, int start, int end){ int size = end / 32 + end % 32 > 0 ? 1: 0; int tmp_arr[size] = {0}; int index = 1, count = 0; srand(time(NULL)); while(count < num){ index += rand() ; index %= 400 + 1; if (test_bit(tmp_arr, index)) { continue; } else { set_bit(tmp_arr, index); array[count] = index; index = 1; count++; } } return array;}