Z czysto probabilistycznego punktu widzenia oba podejścia są poprawne, a zatem równoważne. Z punktu widzenia algorytmu porównanie musi uwzględniać zarówno precyzję, jak i koszt obliczeniowy.
Box-Muller opiera się na jednolitym generatorze i kosztuje mniej więcej tyle samo, co ten jednolity generator. Jak wspomniano w moim komentarzu, możesz uciec bez połączeń sinusoidalnych lub cosinusowych, jeśli nie bez logarytmu:
- generować aż S = U 2 1 + U 2 2 ≤ 1
U1,U2∼iidU(−1,1)
S=U21+U22≤1
- weź i zdefiniujX1=ZUZ=−2log(S)/S−−−−−−−−−−√
X1=ZU1, X2=ZU2
Ogólny algorytm inwersji wymaga na przykład wywołania odwrotnego normalnego pliku cdf qnorm(runif(N))
w R, co może być bardziej kosztowne niż powyższe i, co ważniejsze, może zawieść w ogonach pod względem precyzji, chyba że funkcja kwantylu jest dobrze zakodowana.
Aby podążać za komentarzami Whubera , porównanie rnorm(N)
i qnorm(runif(N))
przewaga odwrotnego cdf, zarówno w czasie wykonania:
> system.time(qnorm(runif(10^8)))
sutilisateur système écoulé
10.137 0.120 10.251
> system.time(rnorm(10^8))
utilisateur système écoulé
13.417 0.060 13.472` `
i pod względem dopasowania do ogona:
Po komentarzu Radforda Neala na moim blogu , chcę zauważyć, że domyślna wartość rnorm
w R wykorzystuje metodę inwersji, stąd powyższe porównanie odzwierciedla interfejs, a nie samą metodę symulacji! Aby zacytować dokumentację R dotyczącą RNG:
‘normal.kind’ can be ‘"Kinderman-Ramage"’, ‘"Buggy
Kinderman-Ramage"’ (not for ‘set.seed’), ‘"Ahrens-Dieter"’,
‘"Box-Muller"’, ‘"Inversion"’ (the default), or ‘"user-supplied"’.
(For inversion, see the reference in ‘qnorm’.) The
Kinderman-Ramage generator used in versions prior to 1.7.1 (now
called ‘"Buggy"’) had several approximation errors and should only
be used for reproduction of old results. The ‘"Box-Muller"’
generator is stateful as pairs of normals are generated and
returned sequentially. The state is reset whenever it is selected
(even if it is the current normal generator) and when ‘kind’ is
changed.