З чисто імовірнісної точки зору обидва підходи є правильними і, отже, рівнозначними. З алгоритмічної точки зору порівняння повинно враховувати як точність, так і витрати на обчислення.
Box-Muller покладається на рівномірний генератор і коштує приблизно стільки ж, скільки і цей рівномірний генератор. Як згадувалося в моєму коментарі, ви можете піти без синусоїдальних або косинусних дзвінків, якщо не без логарифму:
- генерують поки S = U 2 1 + U 2 2 ≤ 1
U1,U2∼iidU(−1,1)
S=U21+U22≤1
- взяти і визначимоX1=ZU1Z=−2log(S)/S−−−−−−−−−−√
X1=ZU1, X2=ZU2
Загальний алгоритм інверсії вимагає виклику до зворотного нормального cdf, наприклад, qnorm(runif(N))
у R, який може бути дорожчим, ніж зазначене вище, і, що ще важливіше, може бути невдалим у хвостах з точки зору точності, якщо тільки квантильна функція не кодується добре.
Слідкуйте за коментарями, зробленими whuber , порівнянням rnorm(N)
та qnorm(runif(N))
перевагою зворотного cdf, як у часі виконання:
> 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` `
і з точки зору прилягання до хвоста:
Після коментаря Radford Neal у своєму блозі , я хочу зазначити, що за замовчуванням rnorm
у R використовується метод інверсії, отже, вищезгадане порівняння відображається на інтерфейсі, а не на самому методі моделювання! Процитуйте документацію на 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.