10

是否有逆错误函数的 JavaScript 实现?这将实现高斯逆误差函数。近似值没问题。

4

3 回答 3

10

为什么是。有。

以下代码使用内置 JavaScript 函数并实现 Abramowitz 和 Stegun 的算法,如下所述

    function erfinv(x){
        var z;
        var a  = 0.147;                                                   
        var the_sign_of_x;
        if(0==x) {
            the_sign_of_x = 0;
        } else if(x>0){
            the_sign_of_x = 1;
        } else {
            the_sign_of_x = -1;
        }

        if(0 != x) {
            var ln_1minus_x_sqrd = Math.log(1-x*x);
            var ln_1minusxx_by_a = ln_1minus_x_sqrd / a;
            var ln_1minusxx_by_2 = ln_1minus_x_sqrd / 2;
            var ln_etc_by2_plus2 = ln_1minusxx_by_2 + (2/(Math.PI * a));
            var first_sqrt = Math.sqrt((ln_etc_by2_plus2*ln_etc_by2_plus2)-ln_1minusxx_by_a);
            var second_sqrt = Math.sqrt(first_sqrt - ln_etc_by2_plus2);
            z = second_sqrt * the_sign_of_x;
        } else { // x is zero
            z = 0;
        }
  return z;
}
于 2012-09-23T22:13:15.320 回答
2

这篇文章前面提供的函数对我不起作用......在 33 米圆上的 NaN 结果,置信度 65% 表示为 65.0......我根据此处列出的公式编写了以下内容https://en.wikipedia.org/ wiki/Error_function#Inverse_functions并且运行良好:

var _a = ((8*(Math.PI - 3)) / ((3*Math.PI)*(4 - Math.PI)));

function erfINV( inputX )
{
    var _x = parseFloat(inputX);
    var signX = ((_x < 0) ? -1.0 : 1.0 );

    var oneMinusXsquared = 1.0 - (_x * _x);
    var LNof1minusXsqrd  = Math.log( oneMinusXsquared );
    var PI_times_a       = Math.PI * _a ;

    var firstTerm  = Math.pow(((2.0 / PI_times_a) + (LNof1minusXsqrd / 2.0)), 2);
    var secondTerm = (LNof1minusXsqrd / _a);
    var thirdTerm  = ((2 / PI_times_a) + (LNof1minusXsqrd / 2.0));

    var primaryComp = Math.sqrt( Math.sqrt( firstTerm - secondTerm ) - thirdTerm );

    var scaled_R = signX * primaryComp ;
    return scaled_R ;
}
于 2015-09-17T16:25:16.120 回答
1

这是 Abramowitz 和 Stegun 算法的另一种实现(相当于 ptmalcolm 的答案,但更简洁,速度是原来的两倍):

function erfinv(x) {
  // maximum relative error = .00013
  const a  = 0.147  
  //if (0 == x) { return 0 }
  const b = 2/(Math.PI * a) + Math.log(1-x**2)/2
  const sqrt1 = Math.sqrt( b**2 - Math.log(1-x**2)/a )
  const sqrt2 = Math.sqrt( sqrt1 - b )
  return sqrt2 * Math.sign(x)
}

逆误差函数的近似方程

您可以使用以下方法测试速度console.time("erfinv"); for (let i=0; i<1000000000; i++) {erfinv(i/1000000000)}; console.timeEnd("erfinv")

语句优化被注释掉了,if因为它似乎没有什么不同——大概解释器认识到这只是一个等式。

如果您需要更准确的近似值,请查看Wikipedia

于 2021-10-09T20:21:20.277 回答