Моє питання надихає вбудований генератор експоненціальних випадкових чисел R , функція rexp()
. Намагаючись генерувати експоненціально розподілені випадкові числа, багато підручників рекомендують метод зворотного перетворення, як описано на цій сторінці Вікіпедії . Я усвідомлюю, що є інші методи для виконання цього завдання. Зокрема, у вихідному коді R використовується алгоритм, викладений у статті Ahrens & Dieter (1972) .
Я переконав себе, що метод Аренса-Дітера (AD) є правильним. Проте я не бачу вигоди від використання їх методу порівняно з методом зворотного перетворення (ІТ). AD не тільки складніший для впровадження, ніж ІТ. Зрозуміло, що також немає переваги швидкості. Ось мій код R для порівняння обох методів з результатами.
invTrans <- function(n)
-log(runif(n))
print("For the inverse transform:")
print(system.time(invTrans(1e8)))
print("For the Ahrens-Dieter algorithm:")
print(system.time(rexp(1e8)))
Результати:
[1] "For the inverse transform:"
user system elapsed
4.227 0.266 4.597
[1] "For the Ahrens-Dieter algorithm:"
user system elapsed
4.919 0.265 5.213
Порівнюючи код для двох методів, AD малює щонайменше два рівномірних випадкових числа (з функцією Cunif_rand()
), щоб отримати одне експоненціальне випадкове число. ІТ потрібно лише одне єдине випадкове число. Імовірно, основна команда R вирішила проти впровадження ІТ, оскільки передбачала, що прийняття логарифму може бути повільніше, ніж генерування більш рівномірних випадкових чисел. Я розумію, що швидкість прийому логарифмів може бути машинно залежною, але принаймні для мене це навпаки. Можливо, є проблеми навколо чисельної точності ІТ, пов'язаних із особливістю логарифму при 0? Але тоді,
вихідний код R sexp.cпоказує, що реалізація AD також втрачає деяку числову точність, оскільки наступна частина коду С видаляє провідні біти з рівномірного випадкового числа u .
double u = unif_rand();
while(u <= 0. || u >= 1.) u = unif_rand();
for (;;) {
u += u;
if (u > 1.)
break;
a += q[0];
}
u -= 1.;
U пізніше перероблені в вигляді однорідного випадкового числа в іншій частині sexp.c . Поки що, здається, ніби
- ІТ простіше кодувати,
- ІТ швидше, і
- І IT, і AD можливо втрачають числову точність.
Я дуже вдячний, якби хтось міг пояснити, чому R все ще реалізує AD як єдиний доступний варіант для rexp()
.
rexp(n)
було б вузьке місце, різниця в швидкості не є сильним аргументом для змін (принаймні для мене). Мене, можливо, більше турбує числова точність, хоча мені не зрозуміло, який із них був би більш чисельно надійним.