2015-05-02 3 views
21

Utilizzando la notazione scientifica 10^6 in un codice R (come ho abitualmente io) si traduce in un tempo significativamente più lungo di calcolo che usare la rappresentazione calcolatrice 1e6:Perché utilizzare l'esponenziazione (ad es. 10^6) richiede 4 volte più a lungo rispetto all'utilizzo della notazione della calcolatrice (ad es. 1e6) in R?

> system.time(for (t in 1:1e7) x=10^6) 
    utilisateur  système  écoulé 
     4.792  0.000  4.281 
> system.time(for (t in 1:1e7) x=1e6) 
utilisateur  système  écoulé 
     0.804  0.000  1.051 
> system.time(for (t in 1:1e7) x=exp(6*log(10))) 
utilisateur  système  écoulé 
     6.301  0.000  5.702 

Perché è il caso che R ricalcola 10^6 in circa il le stesse volte che calcola exp{6*log(10)}? Capisco il fatto che R esegua una funzione durante il calcolo di 10^6, ma perché è stato codificato in questo modo?

+2

Direi che uno è un numerica letterale che deve essere tradotto solo mentre l'altro è un'espressione che deve essere prima valutata. –

+1

Perché pensi che R calcoli '10^6' tramite' exp (6 * log (10)) '? – cryo111

+0

@ cryo111: Non so come R calcoli '10^6' ma ci vuole tanto quanto usare' exp (6 * log (10)) '. Riformulerò questa frase, grazie. –

risposta

29

È perché 1e6 è un constant, ed è riconosciuto come tale dal parser, mentre 10^6 viene analizzato come una chiamata di funzione che deve essere ulteriormente valutata (da una chiamata alla funzione ^()). Dal momento che il primo evita il costoso overhead di una chiamata di funzione, la valutazione è molto più veloce!

class(substitute(1e6)) 
# [1] "numeric" 
class(substitute(10^6)) 
# [1] "call" 

Per vedere meglio che si tratta di una chiamata, è possibile sezionare in questo modo:

as.list(substitute(10^6)) 
# [[1]] 
# `^` 
# 
# [[2]] 
# [1] 10 
# 
# [[3]] 
# [1] 6 

Alcuni altri casi interessanti:

## negative numbers are actually parsed as function calls 
class(substitute(-1)) 
[1] "call" 

## when you want an integer, 'L' notation lets you avoid a function call 
class(substitute(1000000L)) 
# [1] "integer" 
class(substitute(as.integer(1000000))) 
# [1] "call" 
+0

Casi aggiuntivi molto interessanti! Ma sconcertante. Non avevo mai sentito di usare la L prima (ma non sembra risparmiare tempo quando si assegna un numero negativo) –

+2

@ Xi'an Sì, l'uso di R di un 'L' finale per indicare gli interi è diverso dal suo trattamento di' - 'come una chiamata di funzione. Per quanto ne so, non c'è semplicemente modo di fornire una costante negativa senza eseguire una chiamata di funzione --- no "" 1N "' o simili. –

5

Nel caso di 1e6 si specifica un valore numerico letterale. Non vi è alcun calcolo in corso lì.

Quando si richiede 10^6, R esegue il lavoro di elevare 10 alla sesta potenza. Il ^ è un operatore numerico. Non fa nulla di speciale per la base 10. Non conosce il diverso tra 10^6 e 12^14. Deve fare il calcolo per trovare la risposta.

+0

Grazie. È triste che a 10 non venga assegnato uno status speciale, però! –

+1

L'assegnazione di 10 stati speciali complicherebbe il parser. Ovviamente non ho fatto test, ma è probabile che questo rallenterà le cose più del calcolo occasionale della potenza. – kasterma

Problemi correlati