Date: Fri, 16 Jul 2004 14:54:20 -0400 "Richard A. DeVenezia" "SAS(r) Discussion" "Richard A. DeVenezia" Re: a very crude macro on calculating factorial..

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

Back to: Top of message | Previous page | Main SAS-L page