C# SQL Server中的BetaInv函数

C# SQL Server中的BetaInv函数,c#,.net,sql-server,tsql,C#,.net,Sql Server,Tsql,与问题类似:我需要在SQL Server存储过程中使用BetaInv函数 功能描述如下: 是否有人知道TSQL中有类似的内容,或者您会将其封装在CLR.NET托管SQL用户定义函数中 我真的需要在存储过程中使用它,而不是在使用存储过程检索数据后在C#端作为后执行代码使用,因为我应该在db服务器上保留所有逻辑以便更好地重用 我是否可以假设在SQL Server中运行的.NET托管udf的执行速度与正常的本机TSQL函数一样快 谢谢 最后我自己实现了整个函数,这里是源代码,以防有人需要它:

与问题类似:我需要在SQL Server存储过程中使用BetaInv函数

功能描述如下:

是否有人知道TSQL中有类似的内容,或者您会将其封装在CLR.NET托管SQL用户定义函数中

我真的需要在存储过程中使用它,而不是在使用存储过程检索数据后在C#端作为后执行代码使用,因为我应该在db服务器上保留所有逻辑以便更好地重用

我是否可以假设在SQL Server中运行的.NET托管udf的执行速度与正常的本机TSQL函数一样快


谢谢

最后我自己实现了整个函数,这里是源代码,以防有人需要它:

    public static class UDFs
    {
        private const int MAXIT = 100;
        private const double EPS = 0.0000003;
        private const double FPMIN = 1.0E-30;

        [SqlFunction(Name = "BetaInv", DataAccess = DataAccessKind.Read)]
        public static SqlDouble BetaInv(SqlDouble p, SqlDouble alpha, SqlDouble beta, SqlDouble A, SqlDouble B)
        {    
            return InverseBeta(p.Value, alpha.Value, beta.Value, A.Value, B.Value);
        }

        private static double InverseBeta(double p, double alpha, double beta, double A, double B)
        {
            double x = 0;
            double a = 0;
            double b = 1;
            double precision = Math.Pow(10, -6); // converge until there is 6 decimal places precision

            while ((b - a) > precision)
            {
                x = (a + b) / 2;

                if (IncompleteBetaFunction(x, alpha, beta) > p)
                {
                    b = x;
                }
                else
                {
                    a = x;
                }
            }

            if ((B > 0) && (A > 0))
            {
                x = x * (B - A) + A;
            }

            return x;
        }

        private static double IncompleteBetaFunction(double x, double a, double b)
        {
            double bt = 0;

            if (x <= 0.0)
            {
                return 0;
            }

            if (x >= 1)
            {
                return 1;
            }

            bt = System.Math.Exp(Gammln(a + b) - Gammln(a) - Gammln(b) + a * System.Math.Log(x) + b * System.Math.Log(1.0 - x));

            if (x < ((a + 1.0) / (a + b + 2.0)))
            {
                // Use continued fraction directly.
                return (bt * betacf(a, b, x) / a);
            }
            else
            {
                // Use continued fraction after making the symmetry transformation.
                return (1.0 - bt * betacf(b, a, 1.0 - x) / b);
            }
        }

        private static double betacf(double a, double b, double x)
        {
            int m, m2;
            double aa, c, d, del, h, qab, qam, qap;

            qab = a + b; // These q’s will be used in factors that occur in the coe.cients (6.4.6).
            qap = a + 1.0;
            qam = a - 1.0;

            c = 1.0; // First step of Lentz’s method.

            d = 1.0 - qab * x / qap;

            if (System.Math.Abs(d) < FPMIN)
            {
                d = FPMIN;
            }

            d = 1.0 / d;
            h = d;

            for (m = 1; m <= MAXIT; ++m)
            {
                m2 = 2 * m;
                aa = m * (b - m) * x / ((qam + m2) * (a + m2));
                d = 1.0 + aa * d; //One step (the even one) of the recurrence.

                if (System.Math.Abs(d) < FPMIN)
                {
                    d = FPMIN;
                }

                c = 1.0 + aa / c;

                if (System.Math.Abs(c) < FPMIN)
                {
                    c = FPMIN;
                }

                d = 1.0 / d;
                h *= d * c;

                aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2));
                d = 1.0 + aa * d; // Next step of the recurrence (the odd one).

                if (System.Math.Abs(d) < FPMIN)
                {
                    d = FPMIN;
                }

                c = 1.0 + aa / c;

                if (System.Math.Abs(c) < FPMIN)
                {
                    c = FPMIN;
                }

                d = 1.0 / d;
                del = d * c;
                h *= del;

                if (System.Math.Abs(del - 1.0) < EPS)
                {
                    // Are we done?
                    break;
                }
            }

            if (m > MAXIT)
            {
                return 0;
            }
            else
            {
                return h;
            }
        }

        public static double Gammln(double xx)
        {
            double x, y, tmp, ser;

            double[] cof = new double[] { 76.180091729471457, -86.505320329416776, 24.014098240830911, -1.231739572450155, 0.001208650973866179, -0.000005395239384953 };

            y = xx;
            x = xx;
            tmp = x + 5.5;
            tmp -= (x + 0.5) * System.Math.Log(tmp);

            ser = 1.0000000001900149;

            for (int j = 0; j <= 5; ++j)
            {
                y += 1;
                ser += cof[j] / y;
            }

            return -tmp + System.Math.Log(2.5066282746310007 * ser / x);
        }
    }
}
公共静态类UDF
{
私有常量int MAXIT=100;
私人康斯特双每股收益=0.0000003;
私人常数双FPMIN=1.0E-30;
[SqlFunction(Name=“BetaInv”,DataAccess=DataAccessKind.Read)]
公共静态SqlDouble-BetaInv(SqlDouble-p、SqlDouble-alpha、SqlDouble-beta、SqlDouble-A、SqlDouble-B)
{    
返回InverseData(p.值、alpha.值、beta.值、A.值、B.值);
}
专用静态双反转数据(双p、双alpha、双beta、双A、双B)
{
双x=0;
双a=0;
双b=1;
双精度=Math.Pow(10,-6);//收敛到小数点后6位精度
而((b-a)>精度)
{
x=(a+b)/2;
if(不完全beta函数(x,alpha,beta)>p)
{
b=x;
}
其他的
{
a=x;
}
}
如果((B>0)和&(A>0))
{
x=x*(B-A)+A;
}
返回x;
}
专用静态双不完全BetaFunction(双x,双a,双b)
{
双bt=0;
如果(x=1)
{
返回1;
}
bt=System.Math.Exp(Gammln(a+b)-Gammln(a)-Gammln(b)+a*System.Math.Log(x)+b*System.Math.Log(1.0-x));
如果(x<((a+1.0)/(a+b+2.0)))
{
//直接使用连分数。
返回(bt*betacf(a、b、x)/a);
}
其他的
{
//进行对称变换后使用连分数。
回报率(1.0-bt*betacf(b,a,1.0-x)/b);
}
}
专用静态双betacf(双a、双b、双x)
{
int m,m2;
双aa、c、d、del、h、qab、qam、qap;
qab=a+b;//这些q将用于系数中出现的系数(6.4.6)。
qap=a+1.0;
qam=a-1.0;
c=1.0;//伦茨方法的第一步。
d=1.0——qab*x/qap;
if(系统数学Abs(d)对于(int j=0;j我认为您必须实现自己的。CLR存储过程似乎是一条可行之路。@Michael,Excel确实支持它,我们不确定是否应该用C#编写自己的版本,或者购买数学库的许可证,如极限数值,我做了一些测试,对于BetaDist函数,极限数值版本比我们的m大约快15%我想无论哪种方法,我都会创建一个CLR.NET存储过程,执行我们的c#代码,最终调用极限数值。这听起来是一个不错的计划。我在过去的CLR存储过程中运气不错。祝你好运。我在这里也得到了一些关于如何改进存储过程的建议使conf数组保持静态的速度。。。