(因为这种方法独立于其他已发布的解决方案,包括我已经发布的解决方案,所以我将其作为单独的答复提供)。
如果p的总和很小,则可以以秒(或更少)为单位计算出精确的分布。
我们已经看到建议,分布可能近似为高斯分布(在某些情况下)或泊松分布(在其他情况下)。无论哪种方式,我们都知道它的均值是的总和,其方差是的总和。因此,分布将集中在其平均值的几个标准偏差内,例如 SD在在4到6之间或附近。因此,对于到我们只需要计算和等于(整数)的概率。当大多数p 我σ 2 p 我(1 - p 我)Ž Ž X ķ ķ = μ - ž σ ķ = μ + ž σ p 我σ 2 μ ķ [ μ - ž √μpiσ2pi(1−pi)zzXkk=μ−zσk=μ+zσpi是小的,约等于(但稍小于),所以是保守的,我们可以做计算在区间。例如,当所述的总和等于并选择,以便覆盖尾部井,我们需要计算到盖在 =,仅是28个值。σ2μkp我9Ž=6ķ[9-6 √[μ−zμ−−√,μ+zμ−−√]pi9z=6k[0,27][9−69–√,9+69–√][0,27]
该分布是递归计算的。令是这些伯努利变量中第一个的和的分布。对于从到任何,前变量的总和可以通过两种互斥的方式等于:前变量的总和等于,而为否则,前变量的总和等于,而为。因此我Ĵ 0 我+ 1 我+ 1 Ĵ 我Ĵ 我+ 1 ST 0 我Ĵ - 1 我+ 1 ST 1fiij0i+1i+1jiji+1st0ij−1i+1st1
fi+1(j)=fi(j)(1−pi+1)+fi(j−1)pi+1.
我们只需要 在从到的时间间隔内对积分进行此计算最大值(0 ,μ - ž √j μ+Ž √max(0,μ−zμ−−√) μ+zμ−−√.
当大多数很小时(但是仍然可以与区别开来,并且具有合理的精度),这种方法不会困扰我先前发布的解决方案中使用的浮点舍入误差的大量累积。因此,不需要扩展精度计算。例如,对概率(的数组进行双精度计算,需要计算和之间的和的概率 1 − p i 1 2 16 p i = 1 /(i + 1 )μ = 10.6676 0 31 3 × 10 − 15 z = 6 3.6 × 10 − 8pi1−pi1216pi=1/(i+1)μ=10.6676031)在Mathematica 8中花费了0.1秒,在Excel 2002中花费了1-2秒(都获得了相同的答案)。以四倍的精度重复该过程(在Mathematica中)大约需要2秒,但任何答案的更改都不会超过 x。在 SD 处终止分布到上尾巴,仅损失总概率的。3×10−15z=63.6×10−8
使用Mathematica,另一个对40,000个精度介于0到0.001()的双精度随机值数组的计算花费了0.08秒。μ=19.9093
该算法是可并行化的。只需将的集合分解为大小相等的不相交的子集,每个处理器一个。计算每个子集的分布,然后对结果进行卷积(如果需要,可以使用FFT,尽管这种加速可能是不必要的),以获得完整的答案。这使得即使变大,当您需要向尾巴注视(大)和/或大时,也可以使用。 μ ž Ñpiμzn
具有处理器的变量的数组的时间缩放为。Mathematica的速度约为每秒一百万。例如,对于处理器,变量,总概率为,最后得出标准差进入上尾,万:计算几秒钟的计算时间。如果您对此进行编译,则可以将性能提高两个数量级。米ø (Ñ (μ + ž √nmO(n(μ+zμ−−√)/m)m=1n=20000μ=100z=6n(μ+zμ−−√)/m=3.2
顺便说一下,在这些测试案例中,分布图清楚地显示出一些正偏度:它们是不正常的。
作为记录,这是Mathematica解决方案:
pb[p_, z_] := Module[
{\[Mu] = Total[p]},
Fold[#1 - #2 Differences[Prepend[#1, 0]] &,
Prepend[ConstantArray[0, Ceiling[\[Mu] + Sqrt[\[Mu]] z]], 1], p]
]
(注意:本网站使用的颜色编码对于Mathematica代码毫无意义。特别是,灰色内容不是注释:这是所有工作完成的地方!)
其用法的一个例子是
pb[RandomReal[{0, 0.001}, 40000], 8]
编辑
一个R
解决方案是慢十倍数学在这个测试案例-也许我还没有最佳的编码-但它仍然迅速执行(约一秒钟):
pb <- function(p, z) {
mu <- sum(p)
x <- c(1, rep(0, ceiling(mu + sqrt(mu) * z)))
f <- function(v) {x <<- x - v * diff(c(0, x));}
sapply(p, f); x
}
y <- pb(runif(40000, 0, 0.001), 8)
plot(y)