Answers:
这完全取决于您要寻找什么。以下是一些简短的详细信息和参考。
关于逼近的许多文献都围绕函数
对于。这是因为您提供的功能可以分解为上述功能的一个简单区别(可能通过常数进行调整)。该函数有许多名称,包括“正态分布的上尾”,“右正态积分”和“高斯函数”,仅举几例。您还将看到Mills比率的近似值,即
在这里,我列出了一些您可能感兴趣的出于各种目的的参考。
计算的
计算函数或相关互补误差函数的实际标准是
WJ Cody,误差函数的有理切比雪夫近似,数学。比较 ,1969年,第631--637页。
每个(自重)实现都使用本文。(MATLAB,R等)
“简单”近似
Abramowitz和Stegun有一个基于输入变换的多项式展开式。有些人将其用作“高精度”近似值。我不喜欢它,因为它在零附近表现不佳。例如,它们的近似并没有产生,我认为是一个很大的禁忌。因此,有时会发生坏事。
Borjesson和Sundberg给出了一个简单的近似值,在大多数只需要几位数精度的应用中,它的效果很好。的相对误差是永远不如1%,这是相当不错的考虑它的简单性。基本的近似值是 ,它们对常数的首选是和。该参考是一个=0.339b=5.51
PO Borjesson和CE Sundberg。通信应用中误差函数Q(x)的简单近似。IEEE Trans。公社 ,COM-27(3):639-643,1979年3月。
这是其绝对相对误差的图。
电气工程文献充斥着各种这样的近似值,并且似乎对它们过于关注。他们中的许多人虽然很贫穷,但还是会扩展成非常奇怪和令人费解的表情。
您可能还会看
布莱克 右法线积分的均匀逼近。应用数学与计算,127(2-3):365-374,2002年4月。
拉普拉斯的连续分数
拉普拉斯(Laplace)具有美丽的连续分数,对于每个值,都会产生连续的上下界。就米尔斯比率而言,
我使用的表示法是连续分数的相当标准,即。但是,对于小,此表达式的收敛速度不是很快,并且在时发散了。X X = 0
这个连续的分数实际上产生了许多“简单”边界,这些边界在1900年代中后期被“重新发现”。不难看出,对于“标准”形式的连续分数(即,由正整数系数组成),以奇数(偶数)项截断分数将得到上限(下限)。
因此,拉普拉斯立即告诉我们 这两个边界都是在中间“重新发现”的1900年。就函数而言,这等效于 使用零件简单积分的另一种证明可以在S.Resnick的《随机过程的历险》(Birkhauser,1992年)的第6章(布朗运动)中找到。如相关答案所示,这些边界的绝对相对误差不小于。
特别要注意的是,上面的不等式立即意味着。这个事实也可以用L'Hopital法则来确定。这也有助于解释Borjesson-Sundberg逼近函数形式的选择。任何选择都将渐近等价保持为。参数充当接近零的“连续性校正”。一∈ [ 0 ,1 ] X →交通∞ b
这是函数和两个拉普拉斯边界的图。
CI。C. Lee从1990年代初期就有一篇论文,对小值进行“校正” 。看到
CI。C.李 关于Laplace的连续分数为正整数。安 研究所 统计员。数学。》,44(1):107-120,1992年3月。
杜雷特的《概率:理论与范例》在第三版的第6–7页上提供了的经典上限和下限。它们用于较大值(例如),并且渐近紧密。x x > 3
希望这会帮助您入门。如果您有更具体的兴趣,我也许可以为您指出。
我想我为时已晚,但我想对红衣主教的帖子发表评论,而此评论对于预定的包装盒来说太大了。
对于这个答案,我假设 ; 可以将适当的反射公式用于负。x
我更习惯于自己处理误差函数,但我将尝试根据Mills的比率(如红衣主教的答案所定义重铸我所知道的东西。R (x )
除了使用Chebyshev逼近之外,实际上还有其他方法可以计算(互补)误差函数。由于使用切比雪夫(Chebyshev)逼近法需要存储不少系数,因此,如果数组结构在您的计算环境中有点昂贵(您可以内联系数,但是这些结果看起来像是巴洛克式的),则这些方法可能会有优势。一团糟)。
对于“小”,Abramowitz和Stegun给出了一个表现良好的系列(至少比通常的Maclaurin系列表现更好):
注意的系数在系列可以通过用以下物质开始来计算,然后使用递推公式。将序列实现为求和循环时,这很方便。 c j =
红衣主教给拉普拉斯算子提供了连续分数,作为约束大米尔斯比率的一种方法 ; 鲜为人知的是,连续分数也可用于数值评估。
Lentz,Thompson和Barnett推导了一种算法,用于对连续分数作为无穷乘积进行数值评估,这比计算连续分数“向后”的常规方法更有效。我将不展示通用算法,而是展示它如何专门用于计算米尔斯比率:
其中确定的准确性。
在前面提到的序列开始缓慢收敛的情况下,CF非常有用。您将不得不尝试确定适当的“断点”,以在计算环境中从系列切换到CF。也可以使用渐近级数代替Laplacian CF,但是我的经验是Laplacian CF对于大多数应用程序都足够好。
最后,如果您不需要非常精确地计算(互补)误差函数(即,仅几个有效数字),则由于Serge Winitzki ,因此存在紧凑的 近似值。这是其中之一:
该近似值的最大相对误差为并且随着增加而变得更加准确。 x
(此答复最初是对类似问题的回答,后来又重复出现。OP仅希望“实现”高斯积分,而不一定是“最新技术”。在他的评论中,很明显,这是相对简单的,则最好采用简短的实现。)
正如评论所指出的,您需要集成PDF。有很多方法可以执行积分。很久以前,当计算缓慢而昂贵时,戴维·希尔(David Hill)使用简单的算术(有理函数和幂)求出了近似值。对于典型参数(大约介于和之间),它具有双精度精度。1973年,他在应用统计中发布了一个名为ALNORM.F 的Fortran版本。多年以来,我将其移植到不具有正态(高斯)积分或具有可疑积分(例如Excel)的各种环境中。
您可以在http://people.sc.fsu.edu/~jburkardt/m_src/asa005/alnorm.m中找到MatLab版本(具有适当的属性)。原始Fortran代码的完全未记录的版本显示在“ Koders代码搜索”(sic)网站上。
很多年前,我将此移植到AWK。对于现代开发人员来说,此版本可能更适合于移植,因为它具有类似C的语法(而不是Fortran)以及我在开发和测试时插入的一些附加注释,因为我需要提高其准确性。它出现在下面。
对于那些没有丰富的科学/数学/统计代码移植经验的人,请提一些忠告:一个印刷错误会造成严重的错误,这些错误可能很难被发现。(对此,请相信我,我已经做了很多。) 始终,始终进行仔细而详尽的测试。由于普通的积分/高斯积分/误差函数可用于许多表格和软件中,因此可以简便快捷地将移植函数的大量值制成表格并进行系统比较(例如,通过计算机而不是肉眼观察)正确的值。您可以在我的代码开头看到这样的测试:它在-8.5:8.5(乘以0.1)中生成一个值表,该表可以通过管道(通过STDOUT)传送到另一个程序进行系统检查。
对于具有足够数值分析背景知识的人来说,另一种测试方法是知道如何估计预期误差,这将是对数值进行数值区分并将其与PDF(易于计算)进行比较。
顺便说一句:该代码仅适用于均值为和单位标准偏差(“ sigma”)的情况。但这就是所有的需要:当均值为并且SD为,从到进行积分,只需计算并将其应用即可。alnorm
我测试了Mathematica的端口,该端口alnorm
可将值计算为任意精度。为了比较结果,这是上尾值与的比率的自然对数图。(正的相对误差表示太大。)alnorm
相对于逐渐消失的尾部概率,这些值始终精确到。您可以看到计算在何处切换到渐近公式(在),很明显,随着增加,该公式变得非常精确。该图在处停止,因为此处是双精度幂运算开始下溢的地方。
例如,alnorm[-6.0]
返回而等于的真实值约为,第一个十进制数字不同。
注意:作为此编辑的一部分,我在代码中UPPER_TAIL_IS_ZERO
从更改15.
为16.
:对于到之间的,结果使精度略高一点。(编辑结束。)15 16
#----------------------------------------------------------------------#
# ALNORM.AWK
# Compute values of the cumulative normal probability function.
# From G. Dallal's STAT-SAK (Fortran code).
# Additional precision using asymptotic expression added 7/8/92.
#----------------------------------------------------------------------#
BEGIN {
for (i=-85; i<=85; i++) {
x = i/10
p = alnorm(x, 0)
printf("%3.1f %12.10f\n", x, p)
}
exit
}
function alnorm(z,up, y,aln,w) {
#
# ALGORITHM AS 66 APPL. STATIST. (1973) VOL.22, NO.3:
# Hill, I.D. (1973). Algorithm AS 66. The normal integral.
# Appl. Statist.,22,424-427.
#
# Evaluates the tail area of the standard normal curve from
# z to infinity if up, or from -infinity to z if not up.
#
# LOWER_TAIL_IS_ONE, UPPER_TAIL_IS_ZERO, and EXP_MIN_ARG
# must be set to suit this computer and compiler.
LOWER_TAIL_IS_ONE = 8.5 # I.e., alnorm(8.5,0) = .999999999999+
UPPER_TAIL_IS_ZERO = 16.0 # Changes to power series expression
FORMULA_BREAK = 1.28 # Changes cont. fraction coefficients
EXP_MIN_ARG = -708 # I.e., exp(-708) is essentially true 0
if (z < 0.0) {
up = !up
z = -z
}
if ((z <= LOWER_TAIL_IS_ONE) || (up && z <= UPPER_TAIL_IS_ZERO)) {
y = 0.5 * z * z
if (z > FORMULA_BREAK) {
if (-y > EXP_MIN_ARG) {
aln = .398942280385 * exp(-y) / \
(z - 3.8052E-8 + 1.00000615302 / \
(z + 3.98064794E-4 + 1.98615381364 / \
(z - 0.151679116635 + 5.29330324926 / \
(z + 4.8385912808 - 15.1508972451 / \
(z + 0.742380924027 + 30.789933034 / \
(z + 3.99019417011))))))
} else {
aln = 0.0
}
} else {
aln = 0.5 - z * (0.398942280444 - 0.399903438504 * y / \
(y + 5.75885480458 - 29.8213557808 / \
(y + 2.62433121679 + 48.6959930692 / \
(y + 5.92885724438))))
}
} else {
if (up) { # 7/8/92
# Uses asymptotic expansion for exp(-z*z/2)/alnorm(z)
# Agrees with continued fraction to 11 s.f. when z >= 15
# and coefficients through 706 are used.
y = -0.5*z*z
if (y > EXP_MIN_ARG) {
w = -0.5/y # 1/z^2
aln = 0.3989422804014327*exp(y)/ \
(z*(1 + w*(1 + w*(-2 + w*(10 + w*(-74 + w*706))))))
# Next coefficients would be -8162, 110410
} else {
aln = 0.0
}
} else {
aln = 0.0
}
}
return up ? aln : 1.0 - aln
}
### end of file ###