Results 1 to 11 of 11

Thread: Random number generator reset behaving incorrectly.

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Random number generator reset behaving incorrectly.

    I set the seed to 2 with
    Code:
    Randomize 2
    Then I print 3 numbers (each between 0 and 9 with this
    Code:
    Print Int(Rnd * 10)
    Print Int(Rnd * 10)
    Print Int(Rnd * 10)
    Then I reset the random generator to an unseeded state (theoretically) with the magic number -1 like this
    Code:
    Rnd -1
    Then I set the seed again like this
    Code:
    Randomize 2
    But now when I use this code to print 3 numbers
    Code:
    Print Int(Rnd * 10)
    Print Int(Rnd * 10)
    Print Int(Rnd * 10)
    it gives me 3 numbers that are different from the previous 3 (despite having reset it).

    If I reset it again like this
    Code:
    Rnd -1
    and then again print 3 numbers like this
    Code:
    Print Int(Rnd * 10)
    Print Int(Rnd * 10)
    Print Int(Rnd * 10)
    now it DOES repeat the previous 3 numbers (not the first 3 number during the program's run, but a repeat of the second 3 numbers that were generated after the generator was reset and reinitialized the first time).


    It seems that you can't just call Randomize whenever you want, because that command only works when its in an already unseeded state, which is why the Rnd -1 command is needed to set it into an unseeded state if it has already been seeded. However "initialize the seed" does NOT have the same result as "reset the generator to an unseeded state, and then initialize the seed". Why not? What is going on here? Why doesn't the command for resetting the random number generator (Rnd -1) reset into a truely uninitialized state? What is going on here?

  2. #2
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    14,205

    Re: Random number generator reset behaving incorrectly.

    Randomize should be called only once.
    What would be the point in a random number if you know what it is going to be in advance?
    Even using a seed number such as 2 does not give you a random number at all. The sequence will be the same every time you run the program so you may as well just have an array of numbers and pick them in order. Nothing random there.

  3. #3

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Random number generator reset behaving incorrectly.

    Quote Originally Posted by DataMiser View Post
    Randomize should be called only once.
    What would be the point in a random number if you know what it is going to be in advance?
    Even using a seed number such as 2 does not give you a random number at all. The sequence will be the same every time you run the program so you may as well just have an array of numbers and pick them in order. Nothing random there.

    Quote Originally Posted by DataMiser View Post
    Randomize should be called only once.
    What would be the point in a random number if you know what it is going to be in advance?
    Even using a seed number such as 2 does not give you a random number at all. The sequence will be the same every time you run the program so you may as well just have an array of numbers and pick them in order. Nothing random there.

    I'm trying to create a repeatable pseudo-random number set (useful for computer game level generation, so that the same random locations for the enemies appear each time I start a new game, but not necesarilly close the whole game program), that doesn't require that I me to close down the program each time I want to reset the random number generator.

  4. #4
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Random number generator reset behaving incorrectly.

    Normally use for repeatable testing.
    You may want to throw some random numbers at a function to run some tests.
    Then you may want to make changes and repeat the tests, but to be a fair comparison want to use the same sequence of random numbers, but not go through the hassle of pre-generating an array and having code to select from the array, etc...

  5. #5
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Random number generator reset behaving incorrectly.

    You didn't call Rnd with a negative number before the first time you seeded Randomize.

  6. #6
    PowerPoster
    Join Date
    Jun 2001
    Location
    Trafalgar, IN
    Posts
    4,141

    Re: Random number generator reset behaving incorrectly.

    Like Data, I'm not sure why you would want random repeated numbers but you can accomplish that by calling rnd passing a negative before calling randomize. This should print the same numbers every time you click the button.
    Code:
    Private Sub Command1_Click()
        Rnd -1
        Randomize 2
        
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
    End Sub

  7. #7
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: Random number generator reset behaving incorrectly.

    We can make our generator...
    This is an example. We can see how many hits we can get if we compress the output to 100 values.

    need a listbox and a command button

    Code:
    Dim a&(100)
    
    Function gRnd(Optional n& = 0) As Long
    Static a&, b&
    If a& = 0 Then a& = Timer
    If n& = 0 Then n& = b&
    
    b& = n& + a& \ 123
    a& = b& + a& Mod 13031
    b& = (b& Mod 100) * 100 + (b& \ 100) Mod 100
    gRnd = b&
    End Function
    
    
    Private Sub Command1_Click()
    Dim a1&, i&
    For i = 1 To 2000
    a1& = gRnd() \ 100
    a&(a1&) = a&(a1&) + 1
    Next i
    List1.Enabled = False
    List1.Clear
    For i = 0 To 99
    List1.AddItem CStr(i) & ") " & CStr(a&(i))
    Next i
    List1.Enabled = True
    
    End Sub
    
    Private Sub Form_Load()
    gRnd Timer
    End Sub

  8. #8
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Random number generator reset behaving incorrectly.

    Quote Originally Posted by Ben321 View Post
    ...
    It seems that you can't just call Randomize whenever you want, because that command only works when its in an already unseeded state, which is why the Rnd -1 command is needed to set it into an unseeded state if it has already been seeded. However "initialize the seed" does NOT have the same result as "reset the generator to an unseeded state, and then initialize the seed". Why not? What is going on here? Why doesn't the command for resetting the random number generator (Rnd -1) reset into a truely uninitialized state? What is going on here?
    Because that is the way it works and is stated so in the documentation.
    Using Randomize with the same value for Number does not repeat the previous sequence.
    So you can do Randomize 2 as many times as you want, but it will not repeat the previous sequence.
    To repeat sequences of random numbers, call Rnd with a negative argument immediately before using Randomize with a numeric argument.
    Doing those two actions will now start the sequence at the same point in the pseudo random sequence so you will get the same series of numbers.
    Rnd(<negative number>) generates the same number, using negative number as the seed each time (rather than the previous generated number).
    Rnd(0) gives you the last generated number (which is also the current seed)
    Rnd(<positve number>) or no number uses the last generated number as the seed to generate a new number (which is the seed for the next)

    For any given initial seed, the same number sequence is generated because each successive call to the Rnd function uses the previously generated number as a seed for the next number in the sequence.

    Before calling Rnd, use the Randomize statement without an argument to initialize the random-number generator with a seed based on the system timer.
    By the way, calling Randomize with a number after calling Rnd with a negative number seems redundant. The negative number you pass is significant in choosing a specific starting point in the sequence. Then calling Randomize with a number just chooses another spot in the sequence.
    So, to get the same sequence, both the negative number passed to Rnd, and the seed passed to Randomize have to be the same set of numbers, e.g. Rnd -1; Randomize 2 will give a repeatable series. Rnd -2; Randomize 2 will give a different repeatable series. Likewise, Rnd -1; Randomize 3 will give a different repeatable series.
    So, if you want a fixed series the Randomize portion seems unnecessary. Just doing a Rnd <negative number> will use <negative number> as the seed and put you at a specific spot in the random series, which is what you expected Random <seed> to do.
    Last edited by passel; Nov 21st, 2014 at 07:02 PM.

  9. #9

    Thread Starter
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: Random number generator reset behaving incorrectly.

    Quote Originally Posted by MarkT View Post
    Like Data, I'm not sure why you would want random repeated numbers but you can accomplish that by calling rnd passing a negative before calling randomize. This should print the same numbers every time you click the button.
    Code:
    Private Sub Command1_Click()
        Rnd -1
        Randomize 2
        
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
    End Sub
    Rnd -1 is supposed to reset it, but it doesn't quite. In theory:
    Code:
    Private Sub Command1_Click()
        Rnd -1
        Randomize 2
        
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
    End Sub
    should produce the same output as
    Code:
    Private Sub Command1_Click()
        Randomize 2
        
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
    End Sub
    for the first time it is run, because the Rnd -1 should reset the random number to an uninitialized state (equivalent to having just started the program). But it doesn't.

    Code:
    Private Sub Command1_Click()
        Randomize 2
        
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
    End Sub
    produces a distinctly different output from
    Code:
    Private Sub Command1_Click()
        Rnd -1
        Randomize 2
        
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
    End Sub
    Yes, the above code does repeat the output each time that sub is called, but it doesn't produce the same output that running
    Code:
    Private Sub Command1_Click()
        Randomize 2
        
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
        Debug.Print Int(Rnd * 10)
    End Sub
    for the first time does.

    Is this a bug in the VB6 random number generator?

  10. #10
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: Random number generator reset behaving incorrectly.

    Here is an example to do a comparison from the rnd as provided by vb and mine. For 2000000 random numbers we get equal picked numbers..with vb rnd from 0.985% to 1.015%. That isn't good always. Some times you want more span. So mine random generator can do two things.. one the span is wider, and the other is that you can define the starting point so always you can produce the same random series of numbers.

    To be more easily read out I make a sort so you can read the first and last value.
    So change the remark for a1& = Int(Rnd * 100) and place a remark to this a1& = gRnd \ 100

    Code:
    Dim a&(100)
    
    Function gRnd(Optional n& = 0) As Long
    Static a&, b&
    If a& = 0 Then a& = Timer
    If n& = 0 Then n& = b&
    
    b& = n& + a& \ 123
    a& = b& + a& Mod 13031
    b& = (b& Mod 100) * 100 + (b& \ 100) Mod 100
    gRnd = b&
    End Function
    
    
    Private Sub Command1_Click()
    Dim a1&, i&
    For i = 0 To 99
    a&(i) = 0
    Next i
    For i = 1 To 2000000
    ' a1& = Int(Rnd * 100)
    a1& = gRnd \ 100
    a&(a1&) = a&(a1&) + 1
    Next i
    List1.Enabled = False
    List1.Clear
    QuickSortExtended a(), 0, 99
    For i = 0 To 99
    List1.AddItem CStr(i) & ") " & CStr(a&(i) / 20000)
    Next i
    List1.Enabled = True
    
    End Sub
    
    Private Sub Form_Load()
    gRnd Timer
    End Sub
    Public Sub QuickSortExtended(Arr() As Long, ByVal LB As Long, ByVal UB As Long)
    Dim M1 As Long, M2 As Long
    Dim Piv As Long, Tmp As Long '<- adjust types here, when switching to something different than Long
         If UB - LB = 1 Then
         M1 = LB
          If Arr(M1) > Arr(UB) Then Tmp = Arr(M1): Arr(M1) = Arr(UB): Arr(UB) = Tmp
          Exit Sub
         Else
           M1 = (LB + UB) \ 2
                 If Arr(M1) = Arr(LB) Then
                    M2 = UB - 1
                    M1 = LB
                    Do
                        M1 = M1 + 1
                        If M1 > M2 Then
                            If Arr(UB) < Arr(LB) Then Tmp = Arr(LB): Arr(LB) = Arr(UB): Arr(UB) = Tmp
                            Exit Sub
                        End If
                    Loop Until Arr(M1) <> Arr(LB)
                    Piv = Arr(M1)
                    If M1 > LB Then If Arr(LB) > Piv Then Arr(M1) = Arr(LB): Arr(LB) = Piv: Piv = Arr(M1)
                Else
                    Piv = Arr(M1)
                    M1 = LB
                    Do While (Arr(M1) < Piv): M1 = M1 + 1: Loop
                End If
        End If
        M2 = UB
        Do
          Do While (Arr(M2) > Piv): M2 = M2 - 1: Loop
          If M1 <= M2 Then
            Tmp = Arr(M1): Arr(M1) = Arr(M2): Arr(M2) = Tmp 'swap
            M1 = M1 + 1
            M2 = M2 - 1
          End If
          If M1 > M2 Then Exit Do
          Do While (Arr(M1) < Piv): M1 = M1 + 1: Loop
        Loop
        If LB < M2 Then QuickSortExtended Arr, LB, M2
        If M1 < UB Then QuickSortExtended Arr, M1, UB
    End Sub

  11. #11
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Random number generator reset behaving incorrectly.

    Quote Originally Posted by Ben321 View Post
    Rnd -1 is supposed to reset it, but it doesn't quite. In theory:
    ...
    Is this a bug in the VB6 random number generator?
    Probably didn't read my post #8 yet.
    But no it is not a bug, it is the way it is designed to work.
    There is no such thing as an uninitialized state.
    When you start VB, the random number generator is initialized to the same state every time.
    When you use Randomize with a seed, it is generating a new number from the current state using the seed passed.
    The Rnd function is essentially an array of just over 16 million unique Single values (between 0 and 1) in a pseudo random sequence.
    When ever you start VB, it probably starts at index 0 (its not really an array, but the math behind it will always generate the same sequence so it acts like an array).
    If you use Randomize 2, then you are essentially choosing a new value in the array that is some distance (based on the seed 2) away from the current index (0).
    If you use Randomize 2 again, then you are now move away from the current index (whatever was chosen last time) to a new index.
    So, Randomize 2, or any number repeatedly does not put you at a specific index, it offsets from the current index by a specific (seed generated) amount.
    Using Rnd with a negative number, does use the negative number as a seed and will generate a position in the array specific to that seed.
    So Rnd (-1) will always return the same generated random number.
    Rnd (-2) will always return the same (but different from -1) generated random number.
    So Rnd <negative> number is all you need to do what you thought Randomize <number> should be doing.
    And Rnd(-1); Randomize 2, is just resetting the index to a specific place, and then offsetting a specific offset, so you get to the same spot in the 16+million series, so repeat from that point.
    Last edited by passel; Nov 21st, 2014 at 07:22 PM.

Posting Permissions

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



Click Here to Expand Forum to Full Width