내 질문은 R 의 내장 지수 난수 생성기 인 함수에서 영감을 얻었습니다 rexp()
. 기하 급수적으로 분포 된 난수를 생성하려고 할 때 많은 교과서 에서이 Wikipedia 페이지에 요약 된 역변환 방법을 권장합니다 . 이 작업을 수행하는 다른 방법이 있다는 것을 알고 있습니다. 특히, R 의 소스 코드는 Ahrens & Dieter (1972) 의 논문에 요약 된 알고리즘을 사용합니다 .
나는 AD (Ahrens-Dieter) 방법이 옳다는 것을 확신했다. 여전히, 나는 역변환 (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.cC 코드의 다음 부분이 균일 난수 u 에서 선행 비트를 제거하기 때문에 AD의 구현도 수치 적 정밀도를 잃어버린다는 사실이 밝혀 졌습니다.
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는 코딩하기가 더 쉽고
- IT가 더 빠르며
- IT와 AD 모두 수치 정확도를 잃을 수 있습니다.
R이 여전히 AD를 유일하게 사용 가능한 옵션으로 구현하는 이유를 누군가가 설명 할 수 있다면 정말 감사하겠습니다 rexp()
.
rexp(n)
병목 현상이 발생 하는 단일 시나리오를 생각할 수 없기 때문에 속도의 차이는 (적어도 나에게는) 변화에 대한 강력한 논쟁이 아닙니다. 어떤 수치가 더 신뢰할 수 있는지는 확실하지 않지만 수치 정확도에 대해 더 걱정할 수 있습니다.