dcsimg
Results 1 to 3 of 3

Thread: Squeezing the most out of Randomize and Rnd [vb6 and earlier]

  1. #1

    Thread Starter
    Cumbrian Milk's Avatar
    Join Date
    Jan 2007
    Location
    0xDEADBEEF
    Posts
    2,448

    Squeezing the most out of Randomize and Rnd [vb6 and earlier]

    This article assumes you already know how to use Randomize() and Rnd() to generate a sequence of pseudo random numbers. If you don't know please read How can I use Random numbers? [Tutorial].

    MSDN tells us that in order to vary the sequence of numbers returned by Rnd we should call Randomize to reseed it. Technically Rnd has only one sequence, Randomize works by shifting the starting point. What MSDN does not tell us is that the shift that Randomize performs is limited to small portion of the full sequence of Rnd, 1/256 to be exact.

    In terms of other pseudo random number generators Rnd uses a fairly weak algorithm. The full sequence consists of exactly 16777216 (&h1000000) different numbers (every number being multiple of 1/16777216), divide that by 256 and we are only left with 65536 different entry points. This might well be okay for most applications but it would be nice from time to time to have the option of more than this.

    The solution is really quite simple. MSDN tells us that if we call Rnd with a negative argument then that argument itself is used as the seed. It turns out that seeding like this gives full access to the sequence, all we need to do is supply a suitable volatile number. The two most obvious choices are the returns of Timer() and Now(). Using Rnd -Timer although better than Randomize alone still does not quite allow for all possible entry points. Now() on the other hand allows access to pretty much the whole sequence but as the process casts to a single the least significant bits are chopped off leaving a number which remains static for long periods. Multiply them together and we get a good seed.

    Code:
    Private Sub Form_Load()
      Rnd -Timer * Now
      Randomize
    End Sub
    That's all there is to it, Rnd is now properly randomised (or randomized if you prefer )

    For a better PRNG with a much larger sequence check out the Wichmann-Hill Pseudo Random Number Generator over in the code bank.

    For an under the hood explanation on Rnd and Randomize see this external article on the subject
    W o t . S i g

  2. #2
    New Member
    Join Date
    Mar 2015
    Posts
    3

    Re: Squeezing the most out of Randomize and Rnd [vb6 and earlier]

    Quote Originally Posted by Milk View Post
    In terms of other pseudo random number generators Rnd uses a fairly weak algorithm. The full sequence consists of exactly 16777216 (&h1000000) different numbers (every number being multiple of 1/16777216), divide that by 256 and we are only left with 65536 different entry points.
    I've been trying to test this assertion but I can't seem to verify it. I wrote the following program to test it.

    Code:
    Const STEPS As Long = 100000000    ' 100 million iterations
    Const SIZE  As Long = &H1000000    ' Numbers in sequence
    ReDim a(SIZE) As Boolean
        
    Dim i As Long, r As Single, j As Long, c As Long
    For i = 1 To STEPS
        
        ' Reseed on each iteration to get a new entry point...
        Randomize
        
        ' Get the random number at this entry point...
        r = Rnd()
            
        ' Convert from Single to Long...
        j = r * SIZE
        
        ' Flag it in our array as being visited and increment our unique entry-point count...
        If Not a(j) Then
            a(j) = True
            c = c + 1
        End If
        
    Next
    
    MsgBox "Unique entry points: " & c
    This returns over 300,000 entry points. Not nearly 16+ million but also not 65,536.

    Is there something flawed with this test?
    Last edited by BondDotCom; Jul 30th, 2015 at 10:11 AM. Reason: Clearer example

  3. #3

    Thread Starter
    Cumbrian Milk's Avatar
    Join Date
    Jan 2007
    Location
    0xDEADBEEF
    Posts
    2,448

    Re: Squeezing the most out of Randomize and Rnd [vb6 and earlier]

    Hi, you might have moved on now but I've just noticed your question. I'm not so active these days.

    The test is flawed I'm afraid in that each time you call Rnd you shift the sequence by 1 so the call to Randomize is reseeding from that new position and not the original. To prove the assertion you need to reset the internal state which can be achieved by calling Rnd with a fixed negative argument just before you call Randomize. The idea is to simulate the effect of a single call to Randomize on program start up which is how we are often encouraged to use it. Not sure but if I remember correctly the test needs to be run for a long time (24 hours). You might also find it interesting to count rather than just set booleans, that way you can see exactly how many times each number is visited.
    W o t . S i g

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width