[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.



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