als-statistics
Version:
Modular JS statistics toolkit for Node.js and the browser: descriptive stats, correlations (Pearson/Spearman/Kendall), t-tests & ANOVA (Student/Welch), reliability (Cronbach’s alpha), regression (linear/logistic), clustering (DBSCAN/HDBSCAN), and table/co
49 lines (42 loc) • 2.2 kB
JavaScript
import { betacfNR } from './betacfNR.js';
import { gammaLn } from './gammaLn.js';
import { constants } from './constants.js';
export default class CDF {
static constants = constants
static regularizedIncompleteBeta(x, a, b) {
const { constants } = CDF
if (x <= 0) return 0; if (x >= 1) return 1;
const betaLn = gammaLn(a, constants) + gammaLn(b, constants) - gammaLn(a + b, constants)
const bt = Math.exp(a * Math.log(x) + b * Math.log(1 - x) - betaLn);
let sym = false, xx = x, aa = a, bb = b;
if (x > (a + 1) / (a + b + 2)) { sym = true; xx = 1 - x; aa = b; bb = a; }
let val = bt / aa * betacfNR(xx, aa, bb, constants);
if (sym) val = 1 - val;
return val;
}
static t(t, df) { // tCDF
if (df <= 0) throw new Error("Degrees of freedom must be positive");
if (t === 0) return 0.5;
const x = df / (df + t * t), a = df / 2, b = 0.5;
const ibeta = CDF.regularizedIncompleteBeta(x, a, b);
return (t >= 0) ? 1 - 0.5 * ibeta : 0.5 * ibeta;
}
static f(F, df1, df2) { // fCDF
if (F < 0 || df1 <= 0 || df2 <= 0) throw new Error("Invalid input for F-distribution");
const x = (df1 * F) / (df1 * F + df2), a = df1 / 2, b = df2 / 2;
return CDF.regularizedIncompleteBeta(x, a, b);
}
static phi(x) { // standard normal CDF Φ(x)
if (!Number.isFinite(x)) return x === Infinity ? 1 : x === -Infinity ? 0 : NaN;
if (x > 8) return 1; // далеко в правом хвосте
if (x < -8) return 0; // далеко в левом хвосте
// Φ(x) = 0.5 * (1 + erf(x / sqrt(2))) аппроксимация erf по Abramowitz & Stegun 7.1.26 (ошибка ~1e-7)
const y = Math.abs(x) / Math.SQRT2;
const t = 1 / (1 + 0.3275911 * y);
const a1 = 0.254829592, a2 = -0.284496736, a3 = 1.421413741, a4 = -1.453152027, a5 = 1.061405429;
const poly = (((((a5 * t) + a4) * t) + a3) * t + a2) * t + a1;
const erf_abs = 1 - poly * t * Math.exp(-y * y); // erf(|x|/√2), положительный
const erf = x < 0 ? -erf_abs : erf_abs;
return 0.5 * (1 + erf);
}
}