Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.stat.distribution.binomial

This module contains algorithms for the Binomial Distribution.
License:
Authors:
John Michael Hall
enum BinomialAlgo: int;
Algorithms used to calculate binomial distribution.
BinomialAlgo.direct can be more time-consuming for large values of the number of events (k) or the number of trials (n). Additional algorithms are provided to the user to choose the trade-off between running time and accuracy.
direct
Direct
approxNormal
Approximates binomial distribution with normal distribution. Generally a better approximation when n > 20 and p is far from 0 or 1, but a variety of rules of thumb can help determine when it is appropriate to use.
approxNormalContinuityCorrection
Approximates binomial distribution with normal distribution (including continuity correction). More accurate than BinomialAlgo.approxNormal.
approxPoisson
Approximates binomial distribution with poisson distribution (also requires specifying poissonAlgo). Generally a better approximation when n >= 20 and p <= 0.05 or when n >= 100 and np <= 10.
template binomialPMF(BinomialAlgo binomialAlgo = BinomialAlgo.direct, PoissonAlgo poissonAlgo = PoissonAlgo.gamma)

template binomialPMF(string binomialAlgo, string poissonAlgo = "gamma")
Computes the binomial probability mass function (PMF).
Additional algorithms may be provided for calculating PMF that allow trading off time and accuracy. If approxPoisson is provided, the default is PoissonAlgo.gamma
Parameters:
binomialAlgo algorithm for calculating PMF (default: BinomialAlgo.direct)
poissonAlgo algorithm for poisson approximation (default: PoissonAlgo.gamma)
Examples:
import mir.math.common: approxEqual, pow;

assert(4.binomialPMF(6, 2.0 / 3).approxEqual(15.0 * pow(2.0 / 3, 4) * pow(1.0 / 3, 2)));
// For large values of `n` with `p` not too extreme, can approximate with normal distribution
assert(550_000.binomialPMF!"approxNormal"(1_000_000, 0.55).approxEqual(0.0008019042));
// Or closer with continuity correction
assert(550_000.binomialPMF!"approxNormalContinuityCorrection"(1_000_000, 0.55).approxEqual(0.000801904));
// Poisson approximation is better when `p` is low
assert(10_000.binomialPMF!"approxPoisson"(1_000_000, 0.01).approxEqual(0.00398939));
T binomialPMF(T)(const size_t k, const size_t n, const T p)
if (isFloatingPoint!T);
Parameters:
size_t k value to evaluate PMF (e.g. number of "heads")
size_t n number of trials
T p true probability
pure nothrow @nogc @safe T fp_binomialPMF(T)(const size_t k, const size_t n, const T p)
if (is(T == Fp!size, size_t size));
Computes the binomial probability mass function (PMF) directly with extended floating point types (e.g. Fp!128), which provides additional accuracy for large values of k, n, or p.
Parameters:
size_t k value to evaluate PMF (e.g. number of "heads")
size_t n number of trials
T p true probability
Examples:
fp_binomialPMF provides accurate values for large values of n
import mir.bignum.fp: Fp, fp_log;
import mir.math.common: approxEqual;

assert(1.fp_binomialPMF(1_000_000, Fp!128(0.75)).fp_log!double.approxEqual(binomialLPMF(1, 1_000_000, 0.75)));
template binomialCDF(BinomialAlgo binomialAlgo = BinomialAlgo.direct, PoissonAlgo poissonAlgo = PoissonAlgo.gamma)

template binomialCDF(string binomialAlgo, string poissonAlgo = "gamma")
Computes the binomial cumulative distribution function (CDF).
Additional algorithms may be provided for calculating CDF that allow trading off time and accuracy. If approxPoisson is provided, the default is PoissonAlgo.gamma
Parameters:
binomialAlgo algorithm for calculating CDF (default: BinomialAlgo.direct)
poissonAlgo algorithm for poisson approximation (default: PoissonAlgo.gamma)
Examples:
import mir.math.common: approxEqual, pow;

assert(4.binomialCDF(6, 2.0 / 3).approxEqual(binomialPMF(0, 6, 2.0 / 3) + binomialPMF(1, 6, 2.0 / 3) + binomialPMF(2, 6, 2.0 / 3) + binomialPMF(3, 6, 2.0 / 3) + binomialPMF(4, 6, 2.0 / 3)));
// For large values of `n` with `p` not too extreme, can approximate with normal distribution
assert(550_000.binomialCDF!"approxNormal"(1_000_000, 0.55).approxEqual(0.5));
// Or closer with continuity correction
assert(550_000.binomialCDF!"approxNormalContinuityCorrection"(1_000_000, 0.55).approxEqual(0.500401));
// Poisson approximation is better when `p` is low
assert(10_000.binomialCDF!"approxPoisson"(1_000_000, 0.01).approxEqual(0.5026596));
T binomialCDF(T)(const size_t k, const size_t n, const T p)
if (isFloatingPoint!T);
Parameters:
size_t k value to evaluate CDF (e.g. number of "heads")
size_t n number of trials
T p true probability
template binomialCCDF(BinomialAlgo binomialAlgo = BinomialAlgo.direct, PoissonAlgo poissonAlgo = PoissonAlgo.gamma)

template binomialCCDF(string binomialAlgo, string poissonAlgo = "gamma")
Computes the binomial complementary cumulative distribution function (CCDF).
Additional algorithms may be provided for calculating CCDF that allow trading off time and accuracy. If approxPoisson is provided, the default is PoissonAlgo.gamma
Parameters:
binomialAlgo algorithm for calculating CCDF (default: BinomialAlgo.direct)
poissonAlgo algorithm for poisson approximation (default: PoissonAlgo.gamma)
Examples:
import mir.math.common: approxEqual, pow;

assert(4.binomialCCDF(6, 2.0 / 3).approxEqual(binomialPMF(5, 6, 2.0 / 3) + binomialPMF(6, 6, 2.0 / 3)));
// For large values of `n` with `p` not too extreme, can approximate with normal distribution
assert(550_000.binomialCCDF!"approxNormal"(1_000_000, 0.55).approxEqual(0.5));
// Or closer with continuity correction
assert(550_000.binomialCCDF!"approxNormalContinuityCorrection"(1_000_000, 0.55).approxEqual(0.499599));
// Poisson approximation is better when `p` is low
assert(10_000.binomialCCDF!"approxPoisson"(1_000_000, 0.01).approxEqual(0.4973404));
T binomialCCDF(T)(const size_t k, const size_t n, const T p)
if (isFloatingPoint!T);
Parameters:
size_t k value to evaluate CCDF (e.g. number of "heads")
size_t n number of trials
T p true probability
template binomialInvCDF(BinomialAlgo binomialAlgo = BinomialAlgo.direct, PoissonAlgo poissonAlgo = PoissonAlgo.direct) if (poissonAlgo != PoissonAlgo.gamma)

template binomialInvCDF(string binomialAlgo, string poissonAlgo = "direct")
Computes the binomial inverse cumulative distribution function (InvCDF).
Additional algorithms may be provided for calculating InvCDF that allow trading off time and accuracy. If approxPoisson is provided, the default is PoissonAlgo.direct, which is different from binomialPMF and binomialCDF PoissonAlgo.gamma is not supported.
Parameters:
binomialAlgo algorithm for calculating CDF (default: BinomialAlgo.direct)
poissonAlgo algorithm for poisson approximation (default: PoissonAlgo.direct)
Examples:
assert(0.15.binomialInvCDF(6, 2.0 / 3) == 3);
// For large values of `n` with `p` not too extreme, can approximate with normal distribution
assert(0.5.binomialInvCDF!"approxNormal"(1_000_000, 0.55) == 550_000);
// Or closer with continuity correction
assert(0.500401.binomialInvCDF!"approxNormalContinuityCorrection"(1_000_000, 0.55) == 550_000);
// Poisson approximation is better when `p` is low
assert(0.5026596.binomialInvCDF!"approxPoisson"(1_000_000, 0.01) == 10_000);
size_t binomialInvCDF(T)(const T q, const size_t n, const T p)
if (isFloatingPoint!T);
Parameters:
T q value to evaluate InvCDF
size_t n number of trials
T p true probability
T binomialLPMF(T)(const size_t k, const size_t n, const T p)
if (isFloatingPoint!T);
Computes the binomial log probability mass function (LPMF)
Parameters:
size_t k value to evaluate LPMF (e.g. number of "heads")
size_t n number of trials
T p true probability
Examples:
import mir.math.common: approxEqual, exp;

for (size_t i; i <= 5; i++) {
    assert(i.binomialLPMF(5, 0.5).exp.approxEqual(binomialPMF(i, 5, 0.5)));
    assert(i.binomialLPMF(5, 0.75).exp.approxEqual(binomialPMF(i, 5, 0.75)));
}
Examples:
Accurate values for large values of n
import mir.bignum.fp: Fp, fp_log;
import mir.math.common: approxEqual;

assert(1.binomialLPMF(1_000_000, 0.75).approxEqual(fp_binomialPMF(1, 1_000_000, Fp!128(0.75)).fp_log!double));