(เนื่องจากวิธีการนี้เป็นวิธีการที่ไม่ขึ้นอยู่กับโซลูชันอื่น ๆ ที่โพสต์รวมถึงวิธีที่ฉันโพสต์ไว้ฉันจึงเสนอให้เป็นการตอบแยกต่างหาก)
คุณสามารถคำนวณการกระจายตัวที่แน่นอนในไม่กี่วินาที (หรือน้อยกว่า) หากผลรวมของ p มีขนาดเล็ก
เราได้เห็นคำแนะนำแล้วว่าการกระจายอาจประมาณ Gaussian (ภายใต้บางสถานการณ์) หรือ Poisson (ภายใต้สถานการณ์อื่น) ทั้งสองวิธีที่เรารู้ว่ามันหมายถึงคือผลรวมของและความแปรปรวนของคือผลรวมของ(1-p_i) ดังนั้นการจัดจำหน่ายจะมีความเข้มข้นภายในไม่กี่ค่าเบี่ยงเบนมาตรฐานของค่าเฉลี่ยของการพูด SDS กับระหว่างวันที่ 4 และ 6 หรือราว ดังนั้นเราจึงจำเป็นต้องใช้เพียงคำนวณความน่าจะเป็นที่รวมเท่ากับ (จำนวนเต็ม)สำหรับผ่าน\ เมื่อส่วนใหญ่ของp i σ 2 p i ( 1 - p i ) z z x k k = μ - z σ k = μ + z σ p ฉันσ 2 μ k [ μ - z √μpiσ2pi(1−pi)zzXkk=μ−zσk=μ+zσpiมีขนาดเล็กมีค่าประมาณเท่ากับ (แต่น้อยกว่าเล็กน้อย)ดังนั้นเพื่ออนุรักษ์นิยมเราสามารถทำการคำนวณสำหรับในช่วงเวลาหมู่}] ตัวอย่างเช่นเมื่อผลรวมของเท่ากับและเลือกเพื่อให้ครอบคลุมก้อยดีเราจะต้องคำนวณเพื่อให้ครอบคลุมใน = , ซึ่งเป็นเพียง 28 ค่าσ2μkpi9z=6k[9-6 √[μ−zμ−−√,μ+zμ−−√]pi9z=6k[0,27][9−69–√,9+69–√][0,27]
การกระจายคำนวณซ้ำ ให้เป็นการกระจายตัวของผลรวมของแรกของตัวแปร Bernoulli เหล่านี้ สำหรับจากถึงผลรวมของตัวแปรตัวแรกสามารถเท่ากับในสองวิธีที่ไม่เหมือนกัน: ผลรวมของตัวแปรตัวแรกเท่ากับและคือหรืออื่น ๆ ที่ผลรวมของแรกตัวแปรเท่ากับและเป็น1ดังนั้น i j 0 i + 1 i + 1 j i j i + 1 st 0 i j - 1 i + 1 st 1fiij0i+1i+1jiji+1st0ij−1i+1st1
fi+1(j)=fi(j)(1−pi+1)+fi(j−1)pi+1.
เราต้องทำการคำนวณนี้เพื่ออินทิกรัล ในช่วงเวลาจากถึงสูงสุด( 0 , μ - z √j μ+z √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) ใช้เวลา 0.1 วินาทีกับ Mathematica 8 และ 1-2 วินาทีกับ Excel 2002 (ทั้งคู่ได้คำตอบเดียวกัน) การทำซ้ำที่มีความแม่นยำสี่เท่า (ในมาติกา) ใช้เวลาประมาณ 2 วินาที แต่ไม่ได้เปลี่ยนคำตอบใด ๆ โดยกว่า15} การสิ้นสุดการแจกจ่ายที่ SDs ลงในหางส่วนบนหายไปเพียงของความน่าจะเป็นทั้งหมด3×10−15z=63.6×10−8
การคำนวณอีกครั้งสำหรับอาร์เรย์ของค่าสุ่มที่มีความแม่นยำมากกว่าสองเท่าระหว่าง 0 ถึง 0.001 ( ) ใช้เวลา 0.08 วินาทีกับ Mathematicaμ=19.9093
อัลกอริทึมนี้ขนานได้ เพียงแค่แบ่งชุดของเป็นชุดย่อยที่แยกกันขนาดที่เท่ากันโดยประมาณหนึ่งตัวต่อโปรเซสเซอร์ คำนวณการกระจายสำหรับแต่ละชุดย่อยจากนั้นโน้มน้าวผลลัพธ์ (โดยใช้ FFT หากคุณต้องการแม้ว่าการเร่งความเร็วนี้อาจไม่จำเป็น) เพื่อให้ได้คำตอบเต็ม สิ่งนี้ทำให้ใช้งานได้จริงแม้ในขณะที่มีขนาดใหญ่เมื่อคุณต้องมองออกไปที่หาง (ใหญ่) และ / หรือมีขนาดใหญ่ μ z npiμzn
ระยะเวลาสำหรับอาร์เรย์ของตัวแปรกับเครื่องชั่งน้ำหนักประมวลผลเป็นm) ความเร็วของ Mathematica อยู่ที่ประมาณหนึ่งล้านต่อวินาที ตัวอย่างเช่นด้วยตัวประมวลผล ,ตัวแปร, ความน่าจะเป็นรวมของ , และออกไปที่ส่วนเบี่ยงเบนมาตรฐานในส่วนท้าย,ล้าน: คิดสองสามวินาทีของเวลาในการคำนวณ หากคุณรวบรวมสิ่งนี้คุณอาจเร่งความเร็วของคำสั่งสองขนาดm O ( n ( μ + z √)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]
]
( NBการเขียนโค้ดสีที่เว็บไซต์นี้นำมาใช้นั้นไม่มีความหมายสำหรับรหัส Mathematica โดยเฉพาะอย่างยิ่งสิ่งที่เป็นสีเทาไม่ใช่ความคิดเห็น: เป็นสิ่งที่งานทั้งหมดทำ!)
ตัวอย่างของการใช้งานคือ
pb[RandomReal[{0, 0.001}, 40000], 8]
แก้ไข
คำR
ตอบคือช้ากว่าMathematicaสิบเท่าในกรณีทดสอบ - บางทีฉันไม่ได้เขียนมันอย่างเหมาะสม - แต่มันก็ยังดำเนินการได้อย่างรวดเร็ว (ประมาณหนึ่งวินาที):
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)