Откопал код функции обратного распределения Стьдента, однако при задании высокого уровня надежности p она возвращает весьма отдаленное от СТЬЮДЕНТ.ОБР значение. Есть подозрение, что проблема кроется в константах, заданных в подфункции "NorDev". Если я правильно понял код и Википедию, то NorDev вроде как должна использовать значения гамма-функции, но так ли это не знаю.
В общем, задача заключается в том, чтобы составить код, возвращающий в точности такие же значения как и СТЬЮДЕНТ.ОБР.
Скрытый текст
Код
Function Student(p As Double, f1 As Double) As Double
Dim p4 As Double
Dim x0 As Double
Dim t As Double
Dim sMsg As String
With WorksheetFunction
p4 = p * .Pi()
' точные значения
If (f1 = 1) Then
Student = -Cos(p4) / Sin(p4)
Exit Function
End If
If f1 = 2 Then
Student = Sqr(1# / (2# * p * (1# - p)) - 2#) * Sgn(p - 0.5)
Exit Function
End If
' Модификация Гольдберга и Левина приближения Пизера
If (f1 - 1) * (f1 - 2) <> 0# Then
x0 = NorDev(p)
t = 1# + (1# + x0 * x0) / (4# * f1)
t = t + (3# + 16# * x0 * x0 + 5 * (x0 ^ 4#)) / (96# * f1 * f1)
t = x0 * t
End If
End With
Student = t
Exit Function
End Function
Private Function NorDev(p As Double) As Double
'On Error GoTo ErrH
Dim sMsg As String
'Dim sTit As String
Dim q As Double
Dim X As Double
Dim r As Double
Dim nd As Double
Dim a(4) As Double
Dim b(5) As Double
Dim c(4) As Double
Dim d(3) As Double
a(0) = 2.50662823881
a(1) = -18.6150006252
a(2) = 41.39119773531
a(3) = -25.44106049637
b(0) = 0
b(1) = -8.4735109309
b(2) = 23.08336743743
b(3) = -21.06224101826
b(4) = 3.13082909833
c(0) = -2.78718931138
c(1) = -2.29796479134
c(2) = 4.85014127135
c(3) = 2.32121276858
d(0) = 0
d(1) = 3.54388924762
d(2) = 1.63706781897
q = p - 0.5
If (Abs(q) > 0.42) Then ' хвосты распределения
r = p
If (q > 0) Then r = 1 - p
If (r <= 0) Then ' защита от неправильного ввода
sMsg = "Ошибка данных : P = " & Format(p, "0.000") _
& " и не принадлежит интервалу [0...1]"
Else ' аппроксимация для хвостов распределения
r = Sqr(-Log(r))
X = (((c(3) * r + c(2)) * r + c(1)) * r + c(0))
If (q < 0) Then X = -X
nd = X / ((d(2) * r + d(1)) * r + 1)
End If
Else ' аппроксимация для центральной части распределения
r = q * q
X = q * (((a(3) * r + a(2)) * r + a(1)) * r + a(0))
nd = X / ((((b(4) * r + b(3)) * r + b(2)) * r + b(1)) * r + 1)
End If
NorDev = nd
Exit Function
End Function
где-то в памяти смутно теплится инфа о том, что в Excel статфункции считались "не совсем" точно из-за неправильных алгоритмов. а потом Microsoft "всё поправила". с какой версии - не помню.
может, это как раз такой случай?
фрилансер Excel, VBA - контакты в профиле "Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
ikki, может быть, но если сравнивать результаты Microsoft и самопала с вики, то самопал совсем уж проигрывает. Например, =Student(0.9995;3) возвращает 9,437439..., а СТЬЮДЕНТ.ОБР(0.9995;3) - 12,9239786..., вики на стороне Microsoft.
На одном сайте, где был выложен калькулятор расчета коэффициентов, переработал код под VBA (погрешность с функцией Excel имеется, но в последних знаках, в большинстве случаев этим можно пренебречь):
Скрытый текст
Код
Option Explicit
Function StudT(t As Double, n As Double) As Double
Dim th As Double
Dim Pi As Double
Pi = (4 * Atn(1)) / 2
th = Atn(Abs(t) / Sqr(n))
If n = 1 Then
StudT = 1 - th / Pi
ElseIf n Mod 2 = 1 Then
StudT = 1 - (th + Sin(th) * Cos(th) * StatCom(Cos(th) ^ 2, 2, n - 3)) / Pi
Else
StudT = 1 - Sin(th) * StatCom(Cos(th) ^ 2, 1, n - 3)
End If
End Function
Private Function StatCom(q As Double, i As Double, j As Double) As Double
Dim z As Double
Dim zz As Double
Dim k As Double
zz = 1
z = 1
For k = i To j Step 2
zz = zz * q * k / (k + 1)
z = z + zz
Next
StatCom = z
End Function
Function AStudT(p As Double, n As Double) As Double
Dim v As Double
Dim dv As Double
Dim t As Double
v = 0.5
dv = 0.5
While dv > 1E-18
t = 1 / v - 1
dv = dv / 2
If StudT(t, n) > p Then
v = v - dv
Else: v = v + dv
End If
Wend
AStudT = t
End Function