NormInv Function From Excel
Code originally came from here : http://weblogs.asp.net/esanchez/arch...tion-in-c.aspx, has been converted from c# to vb.
Replicates the Norminv function found in excel.
P needs to be a random number between 0 and 1.
Hopefully this comes in handy for someone.
Code:
'NORMINV DSITRIBUTION
Public Function NormInv(ByVal p As Double, ByVal mu As Double, ByVal sigma As Double) As Double
If p < 0 OrElse p > 1 Then
Throw New ArgumentOutOfRangeException("The probality p must be bigger than 0 and smaller than 1")
End If
If sigma < 0 Then
Throw New ArgumentOutOfRangeException("The standard deviation sigma must be positive")
End If
If p = 0 Then
Return [Double].NegativeInfinity
End If
If p = 1 Then
Return [Double].PositiveInfinity
End If
If sigma = 0 Then
Return mu
End If
Dim q As Double, r As Double, val As Double
q = p - 0.5
'-- use AS 241 ---
' double ppnd16_(double *p, long *ifault)
' ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3
'
' Produces the normal deviate Z corresponding to a given lower
' tail area of P; Z is accurate to about 1 part in 10**16.
'
If Math.Abs(q) <= 0.425 Then
' 0.075 <= p <= 0.925
r = 0.180625 - q * q
val = q * (((((((r * 2509.08092873012 + 33430.5755835881) * r + 67265.7709270087) * r + 45921.9539315499) * r + 13731.6937655095) * r + 1971.59095030655) * r + 133.141667891784) * r + 3.38713287279637) / (((((((r * 5226.49527885285 + 28729.0857357219) * r + 39307.8958000927) * r + 21213.7943015866) * r + 5394.19602142475) * r + 687.187007492058) * r + 42.3133307016009) * r + 1)
Else
' closer than 0.075 from {0,1} boundary
' r = min(p, 1-p) < 0.075
If q > 0 Then
r = 1 - p
Else
r = p
End If
r = Math.Sqrt(-Math.Log(r))
' r = sqrt(-log(r)) <==> min(p, 1-p) = exp( - r^2 )
If r <= 5 Then
' <==> min(p,1-p) >= exp(-25) ~= 1.3888e-11
r += -1.6
val = (((((((r * 0.000774545014278341 + 0.0227238449892692) * r + 0.241780725177451) * r + 1.27045825245237) * r + 3.6478483247632) * r + 5.76949722146069) * r + 4.63033784615655) * r + 1.42343711074968) / (((((((r * 0.00000000105075007164442 + 0.000547593808499535) * r + 0.0151986665636165) * r + 0.14810397642748) * r + 0.6897673349851) * r + 1.6763848301838) * r + 2.05319162663776) * r + 1)
Else
' very close to 0 or 1
r += -5
val = (((((((r * 0.000000201033439929229 + 0.0000271155556874349) * r + 0.00124266094738808) * r + 0.0265321895265761) * r + 0.296560571828505) * r + 1.78482653991729) * r + 5.46378491116411) * r + 6.6579046435011) / (((((((r * 0.00000000000000204426310338994 + 0.000000142151175831645) * r + 0.0000184631831751005) * r + 0.000786869131145613) * r + 0.0148753612908506) * r + 0.136929880922736) * r + 0.599832206555888) * r + 1)
End If
If q < 0.0 Then
val = -val
End If
End If
Return mu + sigma * val
End Function