If you want to use C ++ to generate a random number between 0--n-1, what would you do? You may say that it is very simple. See:
Srand (unsigned) Time (null ));
Rand () % N;
Think about it, is the result random (of course, we do not consider the pseudo-randomness of the Rand () function )?
No, because the upper limit of rand () is rand_max. Generally, rand_max is not an integer multiple of n. If rand_max % = r, the probability of a value between 0 and R is larger, while the probability of a value between R + 1--n-1 is smaller. What should I do if n> rand_max?
The following provides a suitable solution to generate an equi-probability random number result in any range. Finally, there is a simpler method.
1. If n <rand_max + 1, remove the ending number,
R = rand_max-(rand_max + 1) % N; // remove the ending number
T = rand ();
While (T> r) t = rand ();
Result = T % N; // random number that meets the requirements
2. If n> rand_max, you can consider segmented sampling and divide it into [N/(rnad_max + 1)] segments. First, obtain the segments with equal probability and then obtain an element in each segment, in this way, the segmentation is similar to the ending number problem. Instead of just getting to the integer segment every time, there must be more or less an remainder segment. How to select the value of this part?
Select the data from the remainder segment. First, select an event with the probability of the remainder segment, and then select it separately:
R = n % (rand_max + 1); // Remainder
If (happened (double) r/n) // probability of selecting the remainder
Result = N-R + myrandom (r); // myrandom can be implemented using the code in scenario 1.
Else
Result = rand () + myrandom (N/(rand_max + 1) * (rand_max + 1); // select segments if the remainder segment is not selected
Complete code:
# Include <iostream. h>
# Include <time. h>
# Include <stdlib. h>
Const double minprob = 1.0/(rand_max + 1 );
Bool happened (double probability) // probability 0 ~ 1
{
If (probability <= 0)
{
Return false;
}
If (probability <minprob)
{
Return rand () = 0 & happened (probability * (rand_max + 1 ));
}
If (RAND () <= probability * (rand_max + 1 ))
{
Return true;
}
Return false;
}
Long myrandom (long n) // generates 0 ~ Equal Probability random number between n-1
{
T = 0;
If (n <= rand_max)
{
Long r = rand_max-(rand_max + 1) % N; // The ending number.
T = rand ();
While (T> r)
{
T = rand ();
}
Return T % N;
}
Else
{
Long r = n % (rand_max + 1); // Remainder
If (happened (double) r/n) // The probability of getting the remainder
{
Return N-R + myrandom (R );
}
Else
{
Return rand () + myrandom (N/(rand_max + 1) * (rand_max + 1 );
}
}
}
Another very simple method is to use
Random_shuffle (randomaccessiterator _ first, randomaccessiterator _ last ).
For example, to generate a random number between 0--n-1, you can write
# Include <algorithm>
# Include <vector>
Long myrandom (long N)
{
STD: vector <long> VL (n); // defines a vector of N.
For (long I = 0; I <n; ++ I)
{
Vl [I] = I;
}
STD: random_shuffle (Vl. Begin (), Vl. End ());
Return (* Vl. Begin ());
}
Random_shuffle also has an overloaded version with three parameters.
Random_shuffle (randomaccessiterator _ first, randomaccessiterator _ last, randomnumbergenerator & _ rand)
The third parameter can accept a custom random number generator to randomize the elements between the first two parameters.
The disadvantage of this method is that if only a random number is needed, when n is large, the space consumption is very large!