Javascript中的累积分布函数

时间:2011-03-10 12:10:57

标签: javascript math

我正在寻找一种在Javascript中计算累积分布函数的方法。有没有实现过这个的课程?你有想法让这个工作吗?它不需要100%准确,但我需要对价值有所了解。

http://en.wikipedia.org/wiki/Cumulative_distribution_function

6 个答案:

答案 0 :(得分:9)

我能够借助Is there an easily available implementation of erf() for Python?和维基百科的知识编写自己的函数。

计算不是100%正确,因为它只是一个近似值。

function normalcdf(mean, sigma, to) 
{
    var z = (to-mean)/Math.sqrt(2*sigma*sigma);
    var t = 1/(1+0.3275911*Math.abs(z));
    var a1 =  0.254829592;
    var a2 = -0.284496736;
    var a3 =  1.421413741;
    var a4 = -1.453152027;
    var a5 =  1.061405429;
    var erf = 1-(((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*Math.exp(-z*z);
    var sign = 1;
    if(z < 0)
    {
        sign = -1;
    }
    return (1/2)*(1+sign*erf);
}

normalcdf(30, 25, 1.4241); //-> 0.000223264606750539
//wolframalpha.com              0.000223221102572082

答案 1 :(得分:2)

这是一种强制实施,但准确到更高的精度数字。上述近似值在10 ^ -7范围内是准确的。我的实现运行速度较慢(700纳秒),但在10 ^ -14范围内准确。 normal(25,30,1.4241)=== 0.00022322110257305683,vs。wolfram's 0.000223221102572082。

它采用标准普通pdf的幂级数,即钟形曲线,然后整合该系列。

我最初是用C编写的,所以我承认一些优化可能在Javascript中看起来很愚蠢。

function normal(x, mu, sigma) {
    return stdNormal((x-mu)/sigma);
}

function stdNormal(z) {
    var j, k, kMax, m, values, total, subtotal, item, z2, z4, a, b;

    // Power series is not stable at these extreme tail scenarios
    if (z < -6) { return 0; }
    if (z >  6) { return 1; }

    m      = 1;        // m(k) == (2**k)/factorial(k)
    b      = z;        // b(k) == z ** (2*k + 1)
    z2     = z * z;    // cache of z squared
    z4     = z2 * z2;  // cache of z to the 4th
    values = [];

    // Compute the power series in groups of two terms.
    // This reduces floating point errors because the series
    // alternates between positive and negative.
    for (k=0; k<100; k+=2) {
        a = 2*k + 1;
        item = b / (a*m);
        item *= (1 - (a*z2)/((a+1)*(a+2)));
        values.push(item);
        m *= (4*(k+1)*(k+2));
        b *= z4;
    }

    // Add the smallest terms to the total first that
    // way we minimize the floating point errors.
    total = 0;
    for (k=49; k>=0; k--) {
        total += values[k];
    }

    // Multiply total by 1/sqrt(2*PI)
    // Then add 0.5 so that stdNormal(0) === 0.5
    return 0.5 + 0.3989422804014327 * total;
}

答案 2 :(得分:2)

math.js库提供了erf功能。根据{{​​3}}中的定义,cdfNormal函数可以在Javascript中实现:

const mathjs = require('mathjs')

function cdfNormal (x, mean, standardDeviation) {
  return (1 - mathjs.erf((mean - x ) / (Math.sqrt(2) * standardDeviation))) / 2
}

Wolfram Alpha控制台中:

> console.log(cdfNormal(5, 30, 25))
> 0.15865525393145707 // Equal to Wolfram Alpha's result at: https://sandbox.open.wolframcloud.com/app/objects/4935c1cb-c245-4d8d-9668-4d353ad714ec#sidebar=compute

答案 3 :(得分:1)

您还可以查看here,这是一个用javascript实现的科学计算器,它包含erf,其作者声称没有版权的实施。

答案 4 :(得分:1)

由于过去的一些需求,我在javascript中整理了一个分发函数的实现。我的图书馆可以在github上找到。您可以查看https://github.com/chen0040/js-stats

它为正态分布,学生T分布,F分布和卡方分布提供了CDF和逆CDF的javascript实现

使用js lib获取CDF和反CDF:

jsstats = require('js-stats');

//====================NORMAL DISTRIBUTION====================//

var mu = 0.0; // mean
var sd = 1.0; // standard deviation
var normal_distribution = new jsstats.NormalDistribution(mu, sd);

var X = 10.0; // point estimate value 
var p = normal_distribution.cumulativeProbability(X); // cumulative probability

var p = 0.7; // cumulative probability
var X = normal_distribution.invCumulativeProbability(p); // point estimate value

//====================T DISTRIBUTION====================//

var df = 10; // degrees of freedom for t-distribution
var t_distribution = new jsstats.TDistribution(df);

var t_df = 10.0; // point estimate or test statistic
var p = t_distribution.cumulativeProbability(t_df); // cumulative probability

var p = 0.7;
var t_df = t_distribution.invCumulativeProbability(p); // point estimate or test statistic


//====================F DISTRIBUTION====================//

var df1 = 10; // degrees of freedom for f-distribution
var df2 = 20; // degrees of freedom for f-distribution
var f_distribution = new jsstats.FDistribution(df1, df2);

var F = 10.0; // point estimate or test statistic
var p = f_distribution.cumulativeProbability(F); // cumulative probability


//====================Chi Square DISTRIBUTION====================//

var df = 10; // degrees of freedom for cs-distribution
var cs_distribution = new jsstats.ChiSquareDistribution(df);

var X = 10.0; // point estimate or test statistic
var p = cs_distribution.cumulativeProbability(X); // cumulative probability

jsstats = require('js-stats'); //====================NORMAL DISTRIBUTION====================// var mu = 0.0; // mean var sd = 1.0; // standard deviation var normal_distribution = new jsstats.NormalDistribution(mu, sd); var X = 10.0; // point estimate value var p = normal_distribution.cumulativeProbability(X); // cumulative probability var p = 0.7; // cumulative probability var X = normal_distribution.invCumulativeProbability(p); // point estimate value //====================T DISTRIBUTION====================// var df = 10; // degrees of freedom for t-distribution var t_distribution = new jsstats.TDistribution(df); var t_df = 10.0; // point estimate or test statistic var p = t_distribution.cumulativeProbability(t_df); // cumulative probability var p = 0.7; var t_df = t_distribution.invCumulativeProbability(p); // point estimate or test statistic //====================F DISTRIBUTION====================// var df1 = 10; // degrees of freedom for f-distribution var df2 = 20; // degrees of freedom for f-distribution var f_distribution = new jsstats.FDistribution(df1, df2); var F = 10.0; // point estimate or test statistic var p = f_distribution.cumulativeProbability(F); // cumulative probability //====================Chi Square DISTRIBUTION====================// var df = 10; // degrees of freedom for cs-distribution var cs_distribution = new jsstats.ChiSquareDistribution(df); var X = 10.0; // point estimate or test statistic var p = cs_distribution.cumulativeProbability(X); // cumulative probability

答案 5 :(得分:1)

与当前接受的答案不同,此公式将提供正确的正常CDF

function ncdf(x, mean, std) {
  var x = (x - mean) / std
  var t = 1 / (1 + .2315419 * Math.abs(x))
  var d =.3989423 * Math.exp( -x * x / 2)
  var prob = d * t * (.3193815 + t * ( -.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))))
  if( x > 0 ) prob = 1 - prob
  return prob
}

此答案来自math.ucla.edu