Creating Random Numbers Using the System Clock.
A random number generator is useful in the real world for running Monti-Carlo simulations. But, DOS programming is not the real world. What I mean is that creating random numbers in a DOS batch file is almost strictly for fun or just to prove that it can be done. I defy anyone to justify it as truly useful. But being useful is hardly a reason for not doing it, so here is my method for creating two kinds of random numbers -- sort-of-random and nearly-random.

 The Simple Way

The first type is easily generated by determining what the tenths-digit of the system's time-of-day clock is at any given instant. The following batch file, RAND.BAT, does that in what I think is the most straightforward way.

:: RAND.BAT - Uses the system clock to pick a sort-of-random digit, 0 to 9. :: Bug fixed: 18 Mar 97 :: Tom Lavedas <lavedas@pressroom.com> :: http://www.pressroom.com/~tglbatch/ :: Returns the number in the environment variable {RAND}. :: @echo %dbgr% off %1 %0 :: x 0 1 2 3 4 5 6 7 8 9 0 echo.|time> %ram%.\{t} :Loop < %ram%.\{t} find ".%2" > %ram%.\{a} copy %ram%.\{a} %ram%.\{b} > nul if not exist %ram%.\{b} for %%v in (set shift goto:Loop) do %%v {rand}=%4 del %ram%.\{?}
This approach sets up a lookup table of the digits from 0 to 9 as command line inputs in the second line. The third line reads the clock and stores the result in the temporary file, %RAM%.\{T}. The next three lines form a testing loop that compares each of the digits against the clock's tenth-of-a-second digit until it finds a match. The matching digit is saved in the variable {RAND} as the random number. Note the special constuction using the COPY command after the FIND to make the procedure DOS version independent.

This approach returns a fairly random result if a single number is needed based on when the user issues the request for the number. That is, there is direct user interaction needed to create each number. The randomness is assured by the variability in the users actions. However, if multiple calls are made in rapid succession in an automated loop, the results will be decidedly "unrandom", if I can coin a new word. They will instead be rather uniformly spaced as a function of the time it takes to execute the loop and the sequence will tend to repeat itself every few seconds. That's hardly a random sequence.

 A Better Way
One solution that I can think of is to pick from a saved list of numbers that gets shuffled a little with each selection. Then, when the same number comes up in a subsequent cycle, it will likely return a different value out of the list. For example, picking the third item in the list several times in a row gives a different value since the list is in a different order each time. Another benefit of this approach is that it provides a means of selecting numbers from a list of other than digits from 0 to 9, such as the letters of the alphabet. An implementation is offered in the following example.

:: RANDOM.BAT - Picks digit, 0 to 9, randomly using the system clock. :: Requires DOS version 6.xx or later. :: :: Tom Lavedas <lavedas@pressroom.com> :: http://www.pressroom.com/~tglbatch/ :: Returns the selected number in the variable {RANDOM}. :: @echo %dbgr% off %1 if [%#9%]==[] for %%v in (0 1 2 3 4 5 6 7 8 9) do set #%%v=%%v %1 %0 :: 0 %#0% 1 %#1% 2 %#2% 3 %#3% 4 %#4% 5 %#5% 6 %#6% 7 %#7% 8 %#8% 9 %#9% echo.| time > %ram%.\{t} :Loop1 < %ram%.\{t} find ".%2" > nul if errorlevel 1 for %%v in (set shift shift goto:Loop1) do %%v #%2=%3 del %ram%.\{t} set {random}=%3 :Loop2 if not [%4]==[] for %%v in (set shift shift goto:Loop2) do %%v #%2=%5 set #9=%{random}%
The second working line constructs a starting list in normal order the first time the routine is called. The same basic technique described earlier is used to determine the clock's tenth-of-a-second digit, but in this case it isn't returned directly. Instead, the value of the list element corresponding to that number is returned. Of course, the result is the same for the very first pick, but the list becomes more jumbled with each subsequent call. This happens because the selected list item is pulled from the list and placed at its end. For example, if the first number selected is '5', the value of '#5' is placed at the end of the sequence which becomes
#0=0 #1=1 #2=2 #3=3 #4=4 #5=6 #6=7 #7=8 #8=9 #9=5
Selecting '5' a second time returns the value 6 instead, thus randomizing the result a little bit. From my informal testing, the list becomes fairly randomly ordered in just a few picks, being nearly completely jumbled before the number generator completes its first cycle. The only time this won't occur is if the loop requires an exact multiple of one second to be completed. Theoretically, this cannot happen. Practically, it could come close (being a small fraction of a tenth of a second different) and therefore take a long time to randomize the list. Hey, this is DOS remember, not the real world.

The only significant drawback I can see in this second procedure is the need for sufficient environment space to store the ten list items, #0 through #9, and the need for the calling routine to clear them when it is done drawing random numbers. Otherwise, the environment remains cluttered with the variables.

Oh, if a random number between say 00 and 99 is desired, simply call the routine twice and save the first value in another variable before calling it a second time, something like this ...

call random<br> set Number=%{random}%<br> call random<br> set Number=%Number%%{random}%
 Where Do You Go from Here?
So, what can you do with a random number generator like this? Play games, of course. If you're so inclined you can procede to the game page for procedures to simulate flipping a coin or dealing from an infinite deck of cards. It's not serious stuff, but it might be mildly amusing.



Top | General Notes | Homepage