La mia domanda è ispirata al generatore di numeri casuali esponenziale incorporato di R , la funzione rexp()
. Quando si tenta di generare numeri casuali distribuiti in modo esponenziale, molti libri di testo raccomandano il metodo di trasformazione inversa come indicato in questa pagina di Wikipedia . Sono consapevole che esistono altri metodi per svolgere questo compito. In particolare, il codice sorgente di R utilizza l'algoritmo descritto in un documento di Ahrens & Dieter (1972) .
Mi sono convinto che il metodo Ahrens-Dieter (AD) sia corretto. Tuttavia, non vedo il vantaggio di usare il loro metodo rispetto al metodo di trasformazione inversa (IT). AD non è solo più complesso da implementare rispetto all'IT. Nemmeno sembra esserci un vantaggio in termini di velocità. Ecco il mio codice R per confrontare entrambi i metodi seguiti dai risultati.
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)))
risultati:
[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
Confrontando il codice per i due metodi, AD disegna almeno due numeri casuali uniformi (con la funzione Cunif_rand()
) per ottenere un numero casuale esponenziale. L'IT ha bisogno solo di un numero casuale uniforme. Presumibilmente il team di core R ha deciso di non implementare l'IT perché ha assunto che il logaritmo potrebbe essere più lento della generazione di numeri casuali più uniformi. Capisco che la velocità di acquisizione dei logaritmi può dipendere dalla macchina, ma almeno per me è vero il contrario. Forse ci sono problemi nella precisione numerica dell'IT che hanno a che fare con la singolarità del logaritmo a 0? Ma poi, il
codice sorgente R sexp.crivela che l'implementazione di AD perde anche una certa precisione numerica perché la seguente porzione di codice C rimuove i bit iniziali dal numero casuale uniforme 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 è successivamente riciclato come un numero casuale uniforme nella restante sexp.c . Finora sembra che
- L'IT è più facile da codificare,
- L'IT è più veloce e
- sia l'IT che l'AD probabilmente perdono la precisione numerica.
Gradirei davvero se qualcuno potesse spiegare perché R implementa ancora AD come l'unica opzione disponibile per rexp()
.
rexp(n)
verifichino i colli di bottiglia, la differenza di velocità non è un argomento forte per il cambiamento (almeno per me). Potrei essere più preoccupato per l'accuratezza numerica, anche se non mi è chiaro quale sarebbe più affidabile dal punto di vista numerico.