DECLARE FUNCTION mRnd# (parm AS LONG)
'Test code for checking out the mRnd# function
'Test 1 prints an unlegended grid of the counts for each value from
'0 to 255 (00 to FF).
'Test 2 checks for strings of 3 or more of the same byte value
'Test 3 tests the repeat last number functionality
DO
DO
INPUT "Test 1, 2 or 3? (0 to quit) ", Test%
LOOP UNTIL Test% > -1 AND Test% < 4
IF Test% = 0 THEN END
REDIM ra%(0 TO 255)
INPUT "Enter seed: ", x&
x& = -ABS(x&)
x# = mRnd#(x&)
IF Test% = 1 THEN 'run Test 1
FOR rdx% = 1 TO 8192
Rn% = INT(mRnd#(1) * 256)
ra%(Rn%) = ra%(Rn%) + 1
NEXT rdx%
PRINT : PRINT
zCount& = 0
FOR rdx% = 0 TO 255
IF rdx% MOD 16 = 0 THEN PRINT
PRINT USING "####&"; ra%(rdx%); " ";
IF ra%(rdx%) = 0 THEN zCount& = zCount& + 1
NEXT rdx%
PRINT
PRINT "Total numbers in range with no hits ="; zCount&
ELSEIF Test% = 2 THEN 'run Test 2
Ln% = -1
FOR rdx& = 1 TO 1000000
Rn% = INT(mRnd#(1) * 256)
IF Ln% = Rn% THEN
Lc% = Lc% + 1
ELSE
IF Lc% > 2 THEN
PRINT Ln%; "repeated"; Lc%; "times."
END IF
Lc% = 0
Ln% = Rn%
END IF
NEXT rdx&
PRINT : PRINT "End of run"
ELSE 'run Test 3
FOR rdx% = 1 TO 10
PRINT mRnd#(1);
FOR rdx& = 1 TO rdx%
PRINT mRnd#(0);
NEXT rdx&
PRINT : PRINT
NEXT rdx%
END IF
LOOP
END
FUNCTION mRnd# (parm AS LONG)
'mRnd# - generate random numbers using multiple generators
'Generator 0 is used to select which of the generators 1 through
'MAXGEN will be used to get the next random number
'The value passed to the function determines the action performed
'by mRnd#. Any positive value returns the next random number. Zero
'returns the last random number generated. A negative number seeds
'all of the generators from 0 to MAXGEN.
'Because the array doesn't get dimensioned until the generators are
'seeded, a negative value must be passed to mRnd# before any random
'number calls are issued, otherwise the function will crash with a
'"subscript out of range" error.
'The numbers returned by mRnd# are not evenly distributed. I have
'found that a large number for MAXGEN at least eliminates the number
'of complete misses for a range of 0 - 255. As Mac pointed out,
'these "gaps" should not make a significant difference for encryp-
'tion purposes, although for game programming it might be a problem.
'Still considering encryption, strings of the same number could be
'a problem, and this would need to be alleviated by the encryption
'program.
'Running Test two (Test% = 2) checks the output of a million numbers,
'and with the seeds that I randomly keyed in, there were no instancese
'of numbers repeated more than once in the range 0 - 255 (i.e. three
'of the same number on three successive calls)
'number of generators, not including 0
CONST MAXGEN = 4096
'array for saving seeds
STATIC Seed() AS DOUBLE
'last random number, working copy of parm argument
STATIC lRnd AS DOUBLE, prm AS DOUBLE
'random number, seed index, work variable
DIM Rn AS DOUBLE, Sd AS DOUBLE, Temp AS DOUBLE
IF parm > 0 THEN 'return next random number
'get number of generator to use
Sd = 0: GOSUB RandomNum
'from 1 to MAXGEN. generate number
Sd = INT(Rn * MAXGEN) + 1: GOSUB RandomNum
'save last generated number
lRnd = Rn
ELSEIF parm < 0 THEN 'seed random number generators
'create/clean up array of seeds
REDIM Seed(0 TO MAXGEN) AS DOUBLE
'make key positive
prm = -parm
'place key in correct range (is this necessary?)
IF prm > 16777216 THEN prm = prm MOD 16777216
'seed generator 0 with given seed
Seed(0) = ABS(parm)
'generate a seed for each generator
FOR lRnd = 1 TO MAXGEN
'generate a random number from previous generator
Sd = lRnd - 1: GOSUB RandomNum
'place that number in current generator's seed
Seed(Sd + 1) = Seed(Sd)
NEXT lRnd
'every call to mRnd# must return a random number, even
'seeding calls, which always return the first number
'generated by the last generator
Sd = MAXGEN: GOSUB RandomNum
lRnd = Rn
'ELSE return previous number
'nothing to do here, number statically saved from last call
END IF
'set function return value
mRnd# = lRnd
'and return to caller
EXIT FUNCTION
RandomNum:
Temp = (16598013# * Seed(Sd) + 12820163)
Seed(Sd) = Temp - INT(Temp / 16777216) * 16777216
Rn = Seed(Sd) / 16777216
RETURN
END FUNCTION
This message has been edited by Kewbie on Sep 10, 2007 7:21 PM
|
|