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.