ICI logo

Intersystem Concepts, Inc.

VB6's Random Number List

Many know that VB's Rnd Function returns a random number, but few realize the returned value is selected from from a repeating list of numbers. The list contains exactly 16777216 random values. Successive references to the Rnd function return the next value from the list, and after 16777216 uses of Rnd the same list begins anew. The Randomize command merely tells VB to start at a different point in the list.

This behavior goes back many versions of Microsoft BASIC. Indeed, even the Microsoft BASIC interpreter from the 1980s operates in this fashion. The program below demonstrates the list repeats in VB6:

Private Sub Command1_Click()
' demonstrate VB's Rnd function
' returns a list that repeats after 16777216 iterations
  Dim lloop&, lrndcount&
  lrndcount& = 2 ^ 24
  ReDim frandom!(lrndcount&)
  ' Randomize so as to start anywhere in the list
  ' copy all random numbers into array
  For lloop& = 1 To lrndcount&
    frandom!(lloop&) = Rnd
  ' after lrndcount& iterations
  ' random number list should have restarted
  ' so compare the list with values stored in array
  For lloop& = 1 To lrndcount&
    If Rnd <> frandom!(lloop&) Then
      Debug.Print "Different random number at loop count "; lloop&
      Exit For
    End If
  If lloop& > lrndcount& Then
    Debug.Print "The list has repeated: all random numbers the same"
  End If
End Sub

A program that uses the Rnd function many times can exhaust the list, then reloop through the same set of random numbers in the same sequence. This repetition can interfere with the intended randomness of your program.

Depending on your program's needs, a possible solution is to periodically skip a few random numbers (by calling the Rnd function and tossing the value returned), however this can be difficult to do in a truly random fashion since there are no truly random processes on most computers.

To create a pseudo-random process, in your program periodically reference the GetTickCount&() API to generate a number, then call the Rnd function to toss that many returned values. This approach will advance your program to a new spot in VB's random number list, and thus increase randomness. The following sample code demonstrates:

Declare Function GetTickCount& Lib "kernel32" ()
Dim lloop&, ftoss!
For lloop& = 1 to GetTickCount&() And 7
  ftoss! = Rnd

If your program operates with very regular timing, GetTickCount& may not introduce enough randomness. For more pseudo-randomness in the number of Rnd values that are tossed, also reference other unpredictably varying computer values, such as free memory. You may find the GlobalMemoryStatus API helpful for this purpose.

Other VB tips