|
Paul M. Dorfman wrote:
> %macro fact (n= , out=) ;
> data fact ;
Type in haste no doubt.
data fact ;
should be
data &out ;
>
> do n = 1 to &n ;
> fact = fact (n) ;
> output ;
> end ;
>
> Moreover, it is easy to see that computer-wise, this code is actually
> less efficient, for each time FACT() is called, its guts have to
> recalculate the entire product instead of just multiplying by the
> next N. Of course, the difference is negligible and virtually
> impossible to notice, unless just for the sake of curiosity we
> recompute a factorial enough times (from N = 1 to 170, 1 million
> times below):
>
> 04 %let n = 170 ;
> 05 data _null_ ;
> 06 do repeat = 1 to 1e6 ;
> 07 fact = 1 ;
> 08 do n = 1 to &n ;
> 09 fact = fact * n ;
> 10 end ;
> 11 end ;
> 12 run ;
> NOTE: DATA statement used (Total process time):
> real time 4.87 seconds
> cpu time 4.87 seconds
>
> 13 data _null_ ;
> 14 do repeat = 1 to 1e6 ;
> 15 do n = 1 to &n ;
> 16 fact = fact (n) ;
> 17 end ;
> 18 end ;
> 19 run ;
> NOTE: DATA statement used (Total process time):
> real time 1:33.79
> cpu time 1:33.54
>
If I had a hat, I would have to tip it to Paul.
FACT is a function that, in Windows, accepts only 172 distinct inputs: The
integers [0...171].
Q for SI: Why does the function do an internal looping calculation instead
of a table lookup to return the factorial value ?
Last I checked, factorial(I) is a constant over time :) The 172 constants
should be computed at SAS system build time.
I am too impatient to wait out a mere 1.5 minutes, but here is a visual you
can use to examine the O() of the looping inside FACT().
Increase i & N upper limits if you are more patient than I. Increase by
step if you are less impatient.
data timing;
do N = 1 to 40 by 2;
t0 = datetime();
do i = 1 to 5e6;
fact = fact(N);
end;
t1 = datetime();
e = t1-t0;
put n= z2. e= z10.6;
output;
end;
run;
symbol1 i=join v=dot;
proc gplot data=timing;
plot e*n;
run;
--
Richard A. DeVenezia
http://www.devenezia.com
|