A discrete distribution assigns a probability to every outcome in its support. Sampling produces one supported value, with likelihood determined by its probability mass function (PMF). The support may be finite or countably infinite, but the practical implementation here focuses on finite distributions. section 12.2
A useful programming abstraction separates what randomness does from how it is generated. IDistribution<T> exposes Sample(); IDiscreteDistribution<T> also exposes Support() and Weight(T). Integer weights stand in for probabilities: a value's probability is its weight divided by the total support weight. This avoids some floating-point normalization errors while making weight calculations more involved. section 12.4
Common finite discrete distributions include:
- The discrete uniform distribution gives every outcome equal weight, like an n-sided die labeled from 0 through n−1. section 12.2
- The Bernoulli distribution produces 0 or 1 with specified weights, like an unfair coin. section 12.13
- The categorical distribution generalizes finite sampling to arbitrary value types, supports, and weights. section 12.13
A weighted marble draw
A bag containing five red, three blue, and two green marbles defines weights 5, 3, and 2. Sampling therefore yields red with probability 0.5, blue with 0.3, and green with 0.2. The same distribution can be filtered to remove a category. section 12.2 section 12.13
Listing 12.1 An interface and the discrete uniform distribution
public interface IDistribution<T>
{
T Sample();
}
public interface IDiscreteDistribution<T> : IDistribution<T>
{
IEnumerable<T> Support();
int Weight(T t);
}
public sealed class DiscreteUniform : IDiscreteDistribution<int>
{
private readonly Random rnd = new();
private readonly int max;
public static DiscreteUniform Distribution(int max)
{
if (max <= 0)
throw new InvalidOperationException();
return new(max);
}
private DiscreteUniform(int max) => this.max = max;
public int Sample() => rnd.Next(max);
public IEnumerable<int> Support() => Enumerable.Range(0, max);
public int Weight(int t) => 0 <= t && t < max ? 1 : 0;
}
The listing shows the generic interfaces alongside a C# discrete-uniform implementation, including validation, support enumeration, weighting, and sampling. section 12.4

