Random number generator in COBOL
This is a random number generator for the ANSI-74 specification of COBOL. It is an implementation of Donald Knuth's random generator from pages 221-222 in Numerical Recipes in Pascal, 1st edition. It can be used for interactive games, but not for anything serious. Since COBOL doesn't have local variable scope, the private variables and paragraphs are prefixed with 'RAN3'. Therefore the risk of name clashes when importing the code into other source files should be easy to avoid.
The generator is initialized by moving a negative number into RANDSEED. Then do a PERFORM RAND.
and read the variable RANDVAR.
Example client program
This example shows how to use the random number generator in another by the use of 'copy' statements. It calculates the average of 1000 random numbers.
IDENTIFICATION DIVISION. PROGRAM-ID. AVERAGES-TEST. AUTHOR. S. ROUG. ENVIRONMENT DIVISION. CONFIGURATION SECTION. SOURCE-COMPUTER. LINUX. DATA DIVISION. WORKING-STORAGE SECTION. COPY "rand-ws.cbl". * Variables for the testing 77 AVERAGE PIC 999V9(9) VALUE 0. PROCEDURE DIVISION. TESTIT. DISPLAY "TEST RANDOM NUMBER GENERATOR". MOVE -2992 TO RANDSEED. PERFORM TESTRUN 1000 TIMES. DIVIDE 1000 INTO AVERAGE. DISPLAY "AVERAGE: ", AVERAGE. STOP RUN. TESTRUN. PERFORM RAND. ADD RANDVAL TO AVERAGE ON SIZE ERROR DISPLAY "OVERFLOW". * DISPLAY RANDVAL. COPY "rand-proc.cbl".
rand-ws.cbl
* Constants * FAC is 1/MBIG 77 RAN3-MSEED PIC 9(9) COMPUTATIONAL VALUE 161803398. 77 RAN3-MBIG PIC 9(10) COMPUTATIONAL VALUE 1000000000. 77 RAN3-FAC PIC 9V9(9) COMPUTATIONAL VALUE 0.000000001. * State variables 77 RANDSEED PIC S9(9) COMPUTATIONAL VALUE -1. 77 RAN3INEXT PIC 99 COMPUTATIONAL. 77 RAN3EXTP PIC 99 COMPUTATIONAL. 77 RANDVAL PIC 9V9(9) COMPUTATIONAL. 01 RAN3MATRIX OCCURS 55 TIMES. 03 RAN3MA PIC S9(10). 77 RAN3-MJ PIC S9(10) COMPUTATIONAL. 77 RAN3-MK PIC S9(10) COMPUTATIONAL. 77 RAN3-I PIC 9999 COMPUTATIONAL. 77 RAN3-J PIC 9999 COMPUTATIONAL. 77 RAN3-K PIC 9999 COMPUTATIONAL.
rand-proc.cbl
* Knuth's random generator from pages 221-222 in * Numerical Recipes in Pascal, 1st edition. * Returns a uniform random deviate between 0.0 and 1.0. * (Uses long integers) * Set randseed to any negative value to (re)initialize the sequence. * Returns the value in global RANDVAL. RAND. IF RANDSEED < 0 PERFORM RAN3-INIT. ADD 1 TO RAN3INEXT. IF RAN3INEXT > 55 MOVE 1 TO RAN3INEXT. ADD 1 TO RAN3EXTP. IF RAN3EXTP > 55 MOVE 1 TO RAN3EXTP. SUBTRACT RAN3MA(RAN3EXTP) FROM RAN3MA(RAN3INEXT) GIVING RAN3-MJ. IF RAN3-MJ < 0 ADD RAN3-MBIG TO RAN3-MJ. MOVE RAN3-MJ TO RAN3MA(RAN3INEXT). MULTIPLY RAN3-MJ BY RAN3-FAC GIVING RANDVAL. * * Initialize the storage for the random generator * RAN3-INIT. ADD RAN3-MSEED TO RANDSEED GIVING RAN3-MJ. IF RAN3-MJ < 0 SUBTRACT RAN3-MJ FROM 0 GIVING RAN3-MJ. PERFORM RAN3-BELOW-MBIG UNTIL RAN3-MJ NOT > RAN3-MBIG. MOVE RAN3-MJ TO RAN3MA(55). MOVE 1 TO RAN3-MK. PERFORM RAN3-INITTBL VARYING RAN3-I FROM 1 BY 1 UNTIL RAN3-I = 55. PERFORM RAN3-SCRM1 4 TIMES. MOVE 0 TO RAN3INEXT. MOVE 31 TO RAN3EXTP. MOVE 1 TO RANDSEED. RAN3-INITTBL. MULTIPLY RAN3-I BY 21 GIVING RAN3-J. DIVIDE RAN3-J BY 55 GIVING RAN3-K. MULTIPLY 55 BY RAN3-K. SUBTRACT RAN3-K FROM RAN3-J. MOVE RAN3-MK TO RAN3MA(RAN3-J). SUBTRACT RAN3-MK FROM RAN3-MJ GIVING RAN3-MK. IF RAN3-MK < 0 ADD RAN3-MBIG TO RAN3-MK. MOVE RAN3MA(RAN3-J) TO RAN3-MJ. RAN3-BELOW-MBIG. SUBTRACT RAN3-MBIG FROM RAN3-MJ. RAN3-SCRM1. PERFORM RAN3-SCRM2 VARYING RAN3-I FROM 1 BY 1 UNTIL RAN3-I > 55. RAN3-SCRM2. ADD 30 TO RAN3-I GIVING RAN3-J. DIVIDE RAN3-J BY 55 GIVING RAN3-K. MULTIPLY 55 BY RAN3-K. SUBTRACT RAN3-K FROM RAN3-J. ADD 1 TO RAN3-J. SUBTRACT RAN3MA(RAN3-J) FROM RAN3MA(RAN3-I). IF RAN3MA(RAN3-I) < 0 ADD RAN3-MBIG TO RAN3MA(RAN3-I).