815.TXT
=====================================================================
Generating Random Numbers
=====================================================================
PRODUCT: R:BASE VERSION: All
=====================================================================
CATALOG: General Information AREA : Data Manipulation
=====================================================================
The basic procedure for generating a random number is to start with a
"seed" number and then perform calculations on the "seed" number to
generate the actual random numbers. Often the random number generated
is used as the "seed" number for the next iteration. The thousandths
part of the time format is used as the "seed" number in an R:BASE
command file to generate random numbers. Various SuperMath functions
and other arithmetic operations generate the random number. The
calculations can be simple or complex; often the simpler calculations
generate the more random number.
The following examples of calculations that generate a random number
use the same "seed" number each time and also use the complete time
value in the calculation. The time format is set so that it looks like
a number.
SET TIME FORMAT hhmmss.sss
SET VAR vtime DOUBLE = (.#TIME)
SET VAR vrandom1 = +
(NINT(((IFRC(.#TIME))*100)/(NINT(.vtime1)/10000)))
SET VAR vrandom2 = +
(IFRC(.#TIME)+NINT(LOG(.vtime1))+NINT(SQRT(.vtime1)))
With the calculation based on time, you are more likely to generate
duplicate numbers when the numbers are calculated in a WHILE loop one
right after the other. This example uses the calculated random number
as the "seed" number for the next iteration. this example generates
fewer duplicate numbers. The numbers are loaded into a table.
-- set the time format so it displays like a number
SET TIME FORMAT hhmmss.sss
-- initialize variables
SET VAR vloop INTEGER = 0, +
vseed INTEGER= (IFRC(.#TIME)), +
vtime1 DOUBLE = .#TIME, +
vmult = (NINT(.vtime1)), +
vincrement = (JDATE(.#DATE)), +
vmod = 65536
WHILE vloop < 1000 THEN
-- calculate the random number, this is used as
-- the seed number for the next iteration
SET VAR vseed = (+
(.vseed * .vmult + .vincrement)/.vmod)
-- if the maximum random number is reached,
-- reset the seed
IF vseed = 32767 THEN
SET VAR vseed = (IFRC(.#TIME))
ENDIF
IF ( vseed IS NULL OR vseed = 0) THEN
ELSE
-- store the random number in a table and
-- increment the loop counter
INSERT INTO random (rand#) VALUES .vseed
SET VAR vloop = (.vloop + 1)
ENDIF
ENDWH
RETURN
To check the randomness of your calculation, generate 1000 numbers and
then graph the result.
You can see that the frequency of the numbers is random. There is no
pattern even though there duplicate numbers might be generated.
To generate a set of unique random numbers, check to see if the number
has already been loaded to the table.
SELECT COUNT(rand#) INTO vtest +
FROM random WHERE rand#=.vseed
IF (vseed IS NULL OR vseed = 0) OR +
vtest <> 0 THEN
ELSE
INSERT INTO random (rand# ) VALUES .vseed
SET VAR vloop = (.vloop + 1)
ENDIF
An IF statement does not require commands in the "true" part.
Sometimes, it is easier to structure the IF statement to check for a
true condition, but only execute commands when the condition is not
true (the ELSE part of the IF statement). The opposite condition for
this IF statement is written using AND to join the conditions and is
more difficult to construct and understand from a logic standpoint.
To generate a random number with a specific number of digits, verify
that the number falls within a range. If the number is larger than the
maximum value, the number is divided by 10; if the number is below the
minimum value, the number is multiplied by 9.
WHILE vrand > 999 THEN
vrand = (.vrand/10)
ENDWH
WHILE vrand < 100 THEN
vrand = (.vrand * 9)
ENDWH
This example returns a three-digit random number. Change the
comparison values depending on the number of digits to return.