Given @math{K} discrete events with different probabilities @math{P[k]}, produce a random value @math{k} consistent with its probability.
The obvious way to do this is to preprocess the probability list by generating a cumulative probability array with @math{K+1} elements:
Note that this construction produces @math{C[K]=1}. Now choose a uniform deviate @math{u} between 0 and 1, and find the value of @math{k} such that @c{$C[k] \le u < C[k+1]$} @math{C[k] <= u < C[k+1]}. Although this in principle requires of order @math{\log K} steps per random number generation, they are fast steps, and if you use something like @math{\lfloor uK \rfloor} as a starting point, you can often do pretty well.
But faster methods have been devised. Again, the idea is to preprocess the probability list, and save the result in some form of lookup table; then the individual calls for a random discrete event can go rapidly. An approach invented by G. Marsaglia (Generating discrete random numbers in a computer, Comm ACM 6, 37-38 (1963)) is very clever, and readers interested in examples of good algorithm design are directed to this short and well-written paper. Unfortunately, for large @math{K}, Marsaglia's lookup table can be quite large.
A much better approach is due to Alastair J. Walker (An efficient method for generating discrete random variables with general distributions, ACM Trans on Mathematical Software 3, 253-256 (1977); see also Knuth, v2, 3rd ed, p120-121,139). This requires two lookup tables, one floating point and one integer, but both only of size @math{K}. After preprocessing, the random numbers are generated in O(1) time, even for large @math{K}. The preprocessing suggested by Walker requires @math{O(K^2)} effort, but that is not actually necessary, and the implementation provided here only takes @math{O(K)} effort. In general, more preprocessing leads to faster generation of the individual random numbers, but a diminishing return is reached pretty early. Knuth points out that the optimal preprocessing is combinatorially difficult for large @math{K}.
This method can be used to speed up some of the discrete random number generators below, such as the binomial distribution. To use if for something like the Poisson Distribution, a modification would have to be made, since it only takes a finite set of @math{K} outcomes.
gsl_ran_discrete
function below.