我的问题是受R的内置指数随机数生成器函数启发的rexp()
。当尝试生成指数分布的随机数时,许多教科书建议使用此Wikipedia页面中概述的逆变换方法。我知道还有其他方法可以完成此任务。特别是,R的源代码使用Ahrens&Dieter(1972)在论文中概述的算法。
我已经说服自己,Ahrens-Dieter(AD)方法是正确的。不过,与逆变换(IT)方法相比,我看不出使用它们的方法的好处。AD不仅比IT实施更复杂。似乎也没有速度上的好处。这是我的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至少绘制两个统一的随机数(使用C函数unif_rand()
)以获得一个指数随机数。IT只需要一个统一的随机数。大概是R核心团队决定不实施IT,因为它假设采用对数可能比生成更统一的随机数慢。我了解对数的获取速度可能与机器有关,但至少对我而言是相反的。也许IT的数值精度与对数为0的奇异性有关吗?但是然后,R
源代码sexp.c揭示了AD的实现也失去了一些数值精度,因为C代码的以下部分从统一随机数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.;
稍后,在sexp.c的其余部分中将u作为统一的随机数回收。到目前为止,似乎
- IT更容易编码,
- IT更快,并且
- IT和AD都可能会丢失数值精度。
如果有人能解释为什么R仍将AD作为实现的唯一可用选项,我将不胜感激rexp()
。
rexp(n)
瓶颈的单一情况,因此速度差异并不是改变的强烈理由(至少对我而言)。我可能会更关心数值精度,尽管我不清楚哪个数值上更可靠。