import epsilon from "./epsilon.js";
/**
* [二项分布](http://en.wikipedia.org/wiki/Binomial_distribution) 是离散概率分布,
* 表示在 n 次相互独立的成功/失败实验中,成功的次数。这类成功/失败实验也称为
* 伯努利试验(Bernoulli trial);当试验次数 `trials = 1` 时,二项分布退化为
* 伯努利分布(Bernoulli Distribution)。
*
* @param {number} trials 试验次数
* @param {number} probability 成功的概率
* @returns {number[]} 输出概率分布
*/
function binomialDistribution(trials, probability) /*: ?number[] */ {
// 检查 `probability` 是否为有效概率(0 ≤ p ≤ 1),
// 并确保 `trials` 是正整数。
if (probability < 0 || probability > 1 || trials <= 0 || trials % 1 !== 0) {
return undefined;
}
// 初始化 `x`(随机变量)和 `cumulativeProbability`(累积分布函数)。
// `cells` 用于存储概率质量函数(PMF)值。
// `binomialCoefficient` 用于计算二项系数。
let x = 0;
let cumulativeProbability = 0;
const cells = [];
let binomialCoefficient = 1;
// 该算法遍历所有可能的结果,直到 `cumulativeProbability` 接近 1,
// 此时我们已经覆盖了该分布的绝大部分概率质量。
do {
// 计算 [概率质量函数(PMF)](https://en.wikipedia.org/wiki/Probability_mass_function)
cells[x] =
binomialCoefficient *
Math.pow(probability, x) *
Math.pow(1 - probability, trials - x);
cumulativeProbability += cells[x];
x++;
binomialCoefficient = (binomialCoefficient * (trials - x + 1)) / x;
// 当 `cumulativeProbability` 接近 1 时,说明我们已经计算了
// 该分布的主要概率范围。
} while (cumulativeProbability < 1 - epsilon);
return cells;
}
export default binomialDistribution;