If you are interested in using the Zipfian distribution (which is often used when modeling processes from sciences or social domains), you do something in accordance with:
- Choose k (skew) to spread
- Precommute cumulative distribution domain (this is just optimization)
- Creating random values for distribution by finding the closest value from the domain
Code example:
List<int> domain = Enumerable.Range(0,1000); // generate your domain double skew = 0.37; // select a skew appropriate to your domain double sigma = domain.Aggregate(0.0d, (z,x) => x + 1.0 / Math.Pow(z+1, skew)); List<double> cummDist = domain.Select( x => domain.Aggregate(0.0d, (z,y) => z + 1.0/Math.Pow(y, skew) * sigma));
Now you can generate random values by selecting the closest value within the domain:
Random rand = new Random(); double seek = rand.NextDouble(); int searchIndex = cummDist.BinarySearch(seek);
You can, of course, generalize this whole process by decoupling the logic that materializes the distribution area from the process that displays and returns the value from this domain.
source share