如何有效计算二项式累积分布函数?
假设我知道“成功”的概率为P。我运行了N次测试,并且看到S成功。该测试类似于抛掷重量不均的硬币(也许正面成功,反面失败)。
我想知道看到S个成功或比S个成功可能性小的几率的大概概率。
例如,如果P为0.3,N为100,而我获得20次成功,那么我正在寻找获得20次 成功的可能性。
如果在另一个避风港上,P为0.3,N为100,而我获得40次成功,那么我正在寻找获得40次成功的可能性。
我知道这个问题与查找二项式曲线下的面积有关,但是:
- 我的数学能力不足以将这些知识转换为有效的代码
 - 虽然我知道二项式曲线会给出准确的结果,但我给人的印象是它本质上效率低下。一种计算近似结果的快速方法就足够了。
 
我应该强调,此计算必须快速,并且理想情况下应该可以使用标准的64位或128位浮点计算来确定。
我正在寻找一个接受P,S和N并返回概率的函数。因为我比数学符号更熟悉代码,所以我希望任何答案都使用伪代码或代码。
回答:
def factorial(n):     if n < 2: return 1
    return reduce(lambda x, y: x*y, xrange(2, int(n)+1))
def prob(s, p, n):
    x = 1.0 - p
    a = n - s
    b = s + 1
    c = a + b - 1
    prob = 0.0
    for j in xrange(a, c + 1):
        prob += factorial(c) / (factorial(j)*factorial(c-j)) \
                * x**j * (1 - x)**(c-j)
    return prob
>>> prob(20, 0.3, 100)
0.016462853241869437
>>> 1-prob(40-1, 0.3, 100)
0.020988576003924564
import mathdef erf(z):
        t = 1.0 / (1.0 + 0.5 * abs(z))
        # use Horner's method
        ans = 1 - t * math.exp( -z*z -  1.26551223 +
                                                t * ( 1.00002368 +
                                                t * ( 0.37409196 + 
                                                t * ( 0.09678418 + 
                                                t * (-0.18628806 + 
                                                t * ( 0.27886807 + 
                                                t * (-1.13520398 + 
                                                t * ( 1.48851587 + 
                                                t * (-0.82215223 + 
                                                t * ( 0.17087277))))))))))
        if z >= 0.0:
                return ans
        else:
                return -ans
def normal_estimate(s, p, n):
    u = n * p
    o = (u * (1-p)) ** 0.5
    return 0.5 * (1 + erf((s-u)/(o*2**0.5)))
>>> normal_estimate(20, 0.3, 100)
0.014548164531920815
>>> 1-normal_estimate(40-1, 0.3, 100)
0.024767304545069813
import mathdef poisson(s,p,n):
    L = n*p
    sum = 0
    for i in xrange(0, s+1):
        sum += L**i/factorial(i)
    return sum*math.e**(-L)
>>> poisson(20, 0.3, 100)
0.013411150012837811
>>> 1-poisson(40-1, 0.3, 100)
0.046253037645840323
以上是 如何有效计算二项式累积分布函数? 的全部内容, 来源链接: utcz.com/qa/433230.html

