[Date Prev][Date Next][Thread Prev][Thread Next]
[Author Index]
[Date Index]
[Thread Index]
[SQR-USERS Info]
[SQRUG Home Page]
"freebie" code / random number generator.
- Subject: "freebie" code / random number generator.
- From: Krisjanis Gale <Krisjanis.Gale@NY.FRB.ORG>
- Date: Fri, 9 Jul 1999 10:56:23 -0400
seeing as how it only took me about 1 hour of research
(i looked at other generators and saw how they worked)
and maybe 2 hours of trial-and-error coding,
i have no qualms about giving this code away...
i know many of you have asked for a decent random number
generator, since SQR and Oracle both DO NOT have a RND
function built-in...
so here's one i wrote.
it's not your typical generator.
it uses the system clock for the initial seeds (two),
counts how many iterations have been performed,
refreshes the seeds every 1000 iterations...
the new seeds includes factors from the previous ones.
it also keeps track of how many times it has "missed"
while trying to generate a new unique number,
and uses this value in creating the next candidate.
and, continuously, each new number plays a role
in altering one of the two seeds upon each iteration.
oh yeah and there's something else, minor - but probably
still important as to why it works rather well - the reason i use
two seeds is because the second seed includes a multiplicand
of the previous value of the first seed.
so the second seed "inherits" properties of the first one,
before it changed again.
basically, it's as complicated as you can get
without sacrificing calculation performance.
the driver code (in the "program" section)
calls the other three procedures to generate and store
5000 unique 5 digit (range: 0 to 99999) numbers...
... in under 3 minutes. (on a P133, even.)
not to shabby, if i do say so myself.
the generated numbers obtained by the generator
are stored in a database table called "random_values".
without further adieu, the code:
--
begin-setup
begin-sql
create table random_values
(N number)
end-sql
end-setup
begin-program
let #RNDINIT=0 ! initialization flag
let #RNDITER=0 ! counts # of iterations
let #RNDSEED1=0 ! seed 1
let #RNDSEED2=0 ! seed 2
let #RNDEXISTS=0 ! used by checkRandom
let #RNDMISSES=0 ! number of "misses"; used in regenerating seed
let #RNDVALUE=0 ! where the new random value is stored
let #RNDRANGE=100000 ! upper range of generated integer
let #NUM=5000 ! number of randoms to generate
let #I=0 ! counter
while #I<#NUM
do generateRandom
do checkRandom
while #RNDEXISTS=1
do generateRandom
do checkRandom
end-while
do storeRandom
let #I=#I+1
let $D1 = to_char(#RNDVALUE)
let $D1 = rpad($D1,8,' ')
let $D2 = to_char(#I)
let $D3 = $D1 || ': ' || $D2
display $D3
end-while
begin-sql
commit
end-sql
! begin-sql
! drop table random_values
! end-sql
! begin-sql
! commit
! end-sql
end-program
begin-procedure generateRandom
if (#RNDINIT=0) or (#RNDITER=1000)
or (#RNDMISSES=100)
begin-select
to_char(sysdate,'hh:mi:ss') &timen1
to_char(sysdate,'dd-yy') &timen2
let #RNDSEED1 = to_number(substr(&timen1,1,2))
+ to_number(substr(&timen1,4,2))*10
+ to_number(substr(&timen1,7,2))*100
+ #RNDSEED1PREV
let #RNDSEED2 = to_number(substr(&timen2,1,2))*100
+ to_number(substr(&timen2,4,2))*1000
+ #RNDSEED2*#RNDITER
from dual
end-select
let #RNDINIT=1
let #RNDITER=0
let #RNDMISSES=0
end-if
let #RNDVALUE=mod(#RNDSEED1+#RNDSEED2+#RNDMISSES,#RNDRANGE)
let #RNDSEED1PREV=#RNDSEED1
let #RNDSEED1=mod(#RNDSEED1*#RNDSEED2+#RNDITER,#RNDRANGE*100)
let #RNDSEED2=mod(#RNDVALUE*(#RNDSEED1PREV+1),#RNDRANGE*10)
let #RNDITER=#RNDITER+1
end-procedure generateRandom
begin-procedure checkRandom
begin-select
count(*) &RNDE
let #RNDEXISTS=&RNDE
from random_values
where N=#RNDVALUE
end-select
if #RNDEXISTS=0
let #RNDMISSES=0
else
let #RNDMISSES=#RNDMISSES+1
end-if
end-procedure checkRandom
begin-procedure storeRandom
begin-sql
insert into random_values
values (#RNDVALUE)
end-sql
if mod(#RNDITER,500)=0 ! commit after every 500 inserts
begin-sql
commit
end-sql
end-if
end-procedure storeRandom
--
enjoy!
(kris)janis p. gale
hrsd - federal reserve bank of new york
x8163