|
"Jack Hamilton" <JackHamilton@FIRSTHEALTH.COM> wrote in message
news:sfcf1872.013@SLCM02.firsthealth.com...
> Apparently I was not clear. It's not the ability to have either
> separate random number streams or a single stream that I think is
> arbitrary. It's the choice of syntax that I think is arbitary. Why
> does CALL RANUNI(x, y) result in multiple streams while x = RANUNI(y)
> result in a single stream? Why not the other way around? Why not CALL
> RANUNIS and CALL RANUNIM for single or multiple streams?
>
> There might be some reasons hidden deep in the underlying structure of
> SAS, but they're not obvious from the point of view of a new user - or
> even an old and jaded user like me.
>
I don't feel the decision was arbitrary, it simply had to be made. I am
sure the choice made in the sea of possibilities most closely matched the
design precepts and compiler technology in place when it was implemented.
Times change, as do precepts and technology.
Would we be better served with RanUniS and RanUniM, or a functional RanUni
(seed, myHandle) where myHandle indicates the stream the next random number
should be drawn from (wherein the 'system' keeps track of the current seed
of stream, thus making the stream not resettable ?)
One thing I didn't hear discussed is that the stream can be altered and
reset during the data step. For any scheme involving reproducible streams,
I mentally picture seed as an index into two giant look up tables. One
table returns the random number, the other returns a seed.
/* demonstrates the stream can be altered
* by changing the seed between calls
* the stream can be reset by resetting the
* seed prior to a call
*/
data _null_;
seed=10; X=10; put seed= X=;call ranuni (seed, X); put seed= X=/;
seed=11; X=11; put seed= X=;call ranuni (seed, X); put seed= X=/;
seed=10; X=10; put seed= X=;call ranuni (seed, X); put seed= X=/;
call ranuni (seed, X); put seed= X=/;
run;
----log----
seed=10 X=10
seed=1824557293 X=0.8496256982
seed=11 X=11
seed=74277740 X=0.034588268
seed=10 X=10
seed=1824557293 X=0.8496256982
seed=1505143707 X=0.7008871565
----log----
data _null_;
seed=10; X=10;
call ranuni (seed, X); put seed= X=/;
call ranuni (seed, X); put seed= X=/;
run;
----log----
seed=1824557293 X=0.8496256982
seed=1505143707 X=0.7008871565
----log----
/* each data step gets same stream
* functional form used and seed > 0
*/
data _null_;
seed=10;
X = ranuni (seed); put seed= X=;
X = ranuni (0); put seed= X=;
run;
data _null_;
seed=10;
X = ranuni (seed); put seed= X=;
X = ranuni (0); put seed= X=;
run;
/* each data step gets 'random' stream based on
* system clock
* functional form used and seed = 0
* if same stream is shown in log it is because
* resolution of clock reading is not high precision
* and both data step had the same clock reading.
*/
data _null_;
seed=0;
X = ranuni (seed); put seed= X=;
X = ranuni (0); put seed= X=;
run;
data _null_;
seed=0;
X = ranuni (seed); put seed= X=;
X = ranuni (0); put seed= X=;
run;
Here is a demonstration that function ranuni() seed=0 indeed seeds the
stream using the system clock.
However the clock precision is not too good because two very fast running
data steps apparently where seeded with the same clock value. The stream
for function ranuni would be better served by grabbing the seed from the now
common 'thermal' register found in many cpus.
6473
6474 data _null_;
6475 seed=0;
6476 X = ranuni (seed); put seed= X=;
6477 X = ranuni (0); put seed= X=;
6478 run;
seed=0 X=0.4432637037
seed=0 X=0.8304284847
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
6479
6480 data _null_;
6481 seed=0;
6482 X = ranuni (seed); put seed= X=;
6483 X = ranuni (0); put seed= X=;
6484 run;
seed=0 X=0.4432637037
seed=0 X=0.8304284847
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
--
Richard A. DeVenezia
http://www.devenezia.com/downloads/sas/macros
|