土木在线论坛 \ 水利工程 \ 水文与水资源工程 \ vb版GammaDist()和GammaInv()两函数的代码

vb版GammaDist()和GammaInv()两函数的代码

发布于:2008-09-26 11:08:26 来自:水利工程/水文与水资源工程 [复制转发]
rt
这两个函数excel里有,也可以在vb里调用,但运算速度有点慢
哪位有vb版的函数代码能不能共享下, no23q@163.com,不盛感激。

自己从matlab里翻译过来,如果有兴趣请大家测试


GammaDist(x,a,b,true):

'%GAMCDF Gamma cumulative distribution function.
'% P = GAMCDF(X,A,B) returns the gamma cumulative distribution
'% function with parameters A and B at the values in X.

Public Function GamCdf(x, a, b) '对应excel中GammaDist(x,a,b,true)函数,计算S曲线
If a <= 0 Or b <= 0 Then GammCdf = "NaN"
GamCdf = GAMMAINC(x / b, a)
p = IIf(p > 1, 1, p)
End Function


'%GAMMAINC Incomplete gamma function.
'% Y = GAMMAINC(X,A) evaluates the incomplete gamma function for
'% corresponding elements of X and A. X and A must be real and the same
'% size (or either can be a scalar). A must also be non-negative.
'% The incomplete gamma function is defined as:
'% http://zanjero.ygblog.com/
'% gammainc(x,a) = 1 ./ gamma(a) .*
'% integral from 0 to x of t^(a-1) exp(-t) dt
'%
'% For any a>=0, as x approaches infinity, gammainc(x,a) approaches 1.
'% For small x and a, gammainc(x,a) ~= x^a, so gammainc(0,0) = 1.
Public Function GAMMAINC(x, a)
Dim amax As Double
amax = 2 ^ 20

ascalar = 1
If a <= amax Then
If a <> 0 And x <> 0 And x < a + 1 Then
xk = x
ak = a
ap = ak
Sum = 1 / ap
del = Sum
Dim i As Double
For i = 1 To 10000
ap = ap + 1
del = xk * del / ap
Sum = Sum + del
Next
GAMMAINC = Sum * Exp(-xk + ak * Log(xk) - GAMMALN(ak))

ElseIf a <> 0 And x <> 0 And x >= a + 1 Then

xk = x
a0 = 1
a1 = x
b0 = 0
b1 = a0
ak = a
fac = 1
n = 1
g = b1
gold = b0

For i = 1 To 10000
gold = g
ana = n - ak
a0 = (a1 + a0 * ana) * fac
b0 = (b1 + b0 * ana) * fac
anf = n * fac
a1 = xk * a0 + anf * a1
b1 = xk * b0 + anf * b1
fac = 1 / a1
g = b1 * fac
n = n + 1

Next
GAMMAINC = 1 - Exp(-xk + ak * Log(xk) - GAMMALN(ak)) * g

End If
Else

End If

End Function

'*******************************************************************************************************************
'%GAMMALN Logarithm of gamma function.
'% Y = GAMMALN(X) computes the natural logarithm of the gamma
'% function for each element of X. GAMMALN is defined as
'%
'% LOG(GAMMA(X))
'%
'% and is obtained without computing GAMMA(X). Since the gamma
'% function can range over very large or very small values, its
'% logarithm is sometimes more useful. http://zanjero.ygblog.com/
Public Function GAMMALN(XX)
Dim COF(6) As Double, stp As Double, half As Double, one As Double
Dim fpf As Double, x As Double, tmp As Double, ser As Double
Dim j As Integer
COF(1) = 76.18009173
COF(2) = -86.50532033
COF(3) = 24.01409822
COF(4) = -1.231739516
COF(5) = 0.00120858003
COF(6) = -0.00000536382
stp = 2.50662827465
half = 0.5
one = 1#
fpf = 5.5
x = XX - one
tmp = x + fpf
tmp = (x + half) * Log(tmp) - tmp
ser = one
For j = 1 To 6
x = x + one
ser = ser + COF(j) / x
Next j
GAMMALN = tmp + Log(stp * ser)
End Function

[ 本帖最后由 no23q 于 2008-10-13 10:52 编辑 ]

全部回复(2 )

只看楼主 我来说两句抢地板
  • zhphto
    zhphto 沙发
    你是想写频率曲线程序还是瞬时单位线推洪水,
    我看论坛里这个叫freeskychenjun 估计有
    2008-10-14 08:26:14

    回复 举报
    赞同0
  • no23q
    no23q 板凳
    '%GAMINV Inverse of the gamma cumulative distribution function (cdf).
    '% X = GAMINV(P,A,B) returns the inverse of the gamma cdf with
    '% parameters A and B, at the probabilities in P. http://zanjero.ygblog.com/
    '对应Excel中GammaInv(p,a,b)函数,计算PⅢ的Φp值 Φp=Cs/2*GammaInv(1-p/100,4/Cs^2,1)-2/Cs
    Public Function gaminv(p, a, b)
    If p < 0 Or p > 1 Or a <= 0 Or b <= 0 Then
    gaminv = "NaN"
    Exit Function

    Else
    Select Case p
    Case 0
    gaminv = 0
    Case 1
    gaminv = 1
    Case Else
    '% Newton's Method
    '% Permit no more than count_limit interations.

    count_limit = 100
    cunt = 0
    pk = p
    '% Supply a starting guess for the iteration.
    '% Use a method of moments fit to the lognormal distribution.

    mn = a * b
    v = mn * b
    temp = Log(v + mn ^ 2)
    mu = 2 * Log(mn) - 0.5 * temp
    sigma = -2 * Log(mn) + temp

    xk = Exp(MyNormInv(pk, mu, sigma)) '''''''''''''''''''''''

    h = 1
    '% Break out of the iteration loop for three reasons:
    '% 1) the last update is very small (compared to x)
    '% 2) the last update is very small (compared to sqrt(eps))
    '% 3) There are more than 100 iterations. This should NEVER happen.
    eps = 2 ^ -10
    Do While Abs(h) > eps ^ 0.5 * Abs(xk) And Abs(h) > eps ^ 0.5 And cunt < count_limit

    cunt = tunt + 1
    h = (GamCdf(xk, a, b) - pk) / gampdf(xk, a, b) '''''''''''''
    xnew = xk - h
    ' % Make sure that the current guess stays greater than zero.
    ' % When Newton's Method suggests steps that lead to negative guesses
    ' % take a step 9/10ths of the way to zero:

    If xnew < 0 Then
    xnew = xk / 10
    h = xk - xnew
    End If
    xk = xnew

    Loop
    gaminv = xk

    End Select

    End If

    End Function


    ' This function is a replacement for the Microsoft Excel Worksheet function NORMSINV.
    ' It uses the algorithm of Peter J. Acklam to compute the inverse normal cumulative
    ' distribution. Refer to http://home.online.no/~pjacklam/notes/invnorm/index.html for
    ' a description of the algorithm.
    ' Adapted to VB by Christian d'Heureuse, http://zanjero.ygblog.com/.
    Public Function MyNormSInv(ByVal p As Double) '计算频率格纸
    Const a1 = -39.6968302866538, a2 = 220.946098424521, a3 = -275.928510446969
    Const a4 = 138.357751867269, a5 = -30.6647980661472, a6 = 2.50662827745924
    Const b1 = -54.4760987982241, b2 = 161.585836858041, b3 = -155.698979859887
    Const b4 = 66.8013118877197, b5 = -13.2806815528857, c1 = -7.78489400243029E-03
    Const c2 = -0.322396458041136, c3 = -2.40075827716184, c4 = -2.54973253934373
    Const c5 = 4.37466414146497, c6 = 2.93816398269878, d1 = 7.78469570904146E-03
    Const d2 = 0.32246712907004, d3 = 2.445134137143, d4 = 3.75440866190742
    Const p_low = 0.02425, p_high = 1 - p_low
    Dim q As Double, r As Double
    If p < 0 Or p > 1 Then
    Err.Raise vbObjectError, , "NormSInv: Argument out of range."
    ElseIf p < p_low Then
    q = Sqr(-2 * Log(p))
    MyNormSInv = (((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / _
    ((((d1 * q + d2) * q + d3) * q + d4) * q + 1)
    ElseIf p <= p_high Then
    q = p - 0.5: r = q * q
    MyNormSInv = (((((a1 * r + a2) * r + a3) * r + a4) * r + a5) * r + a6) * q / _
    (((((b1 * r + b2) * r + b3) * r + b4) * r + b5) * r + 1)
    Else
    q = Sqr(-2 * Log(1 - p))
    MyNormSInv = -(((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) / _
    ((((d1 * q + d2) * q + d3) * q + d4) * q + 1)
    End If
    End Function


    '%GAMPDF Gamma probability density function.
    '% Y = GAMPDF(X,A,B) returns the gamma probability density function
    '% with parameters A and B, at the values in X. http://zanjero.ygblog.com/
    Public Function gampdf(x, a, b)
    y = 0
    If x = 0 And a < 1 Then
    gampdf = "∞"
    Exit Function
    End If

    If x = 0 And a = 1 Then
    gampdf = 1 / b
    Exit Function
    End If

    If a <= 0 Or b <= 0 Then
    y = "NaN"
    gampdf = y
    Exit Function
    ElseIf x > 0 Then

    y = (a - 1) * Log(x) - x / b - GAMMALN(a) - a * Log(b)
    y = Exp(y)
    End If
    gampdf = y

    End Function
    :victory:

    [ 本帖最后由 no23q 于 2008-10-13 10:52 编辑 ]
    2008-10-13 10:49:13

    回复 举报
    赞同0
这个家伙什么也没有留下。。。

水文与水资源工程

返回版块

4.6 万条内容 · 238 人订阅

猜你喜欢

阅读下一篇

提取Dxf中的图元属性(提供源代码C#2.0)

程序来源:1. 项目中要打印CAD中的地形图,需要把过密的高程点均匀删除,于是做了DxfEditer.2.为了提取CAD中的高程点,用于在另一个软件中生成河网,于是做了GetImageObject.DxfEditer的样例文件为DxfEditer.dxf;GetImageObject的样例文件为GetImageObject.dxf.这两个软件与读取dxf文件的类库都在同一个解决方案里,项目都采用组件式编程。

回帖成功

经验值 +10