Tutorial - Random Numbers [VB6 and earlier]-VBForums

Thread: Tutorial - Random Numbers [VB6 and earlier]

1. Tutorial - Random Numbers [VB6 and earlier]

Many questions in VB are regarding random numbers. In this tutorial I will try and explain the basic ideas regarding random numbers so it'll be easier for you to create your applications.

Intro - The Rnd Function

The first thing you need to know is the function that generates a random number. The function is called : Rnd. Here is how you use it :

1) Open a new project in VB.
2) In the load event of your form add the following code :

VB Code:
`Private Sub Form_Load()    Dim i As Integer    For i = 1 To 10        Debug.Print Rnd    NextEnd Sub`

3) Run the project. In the Immediate window you will notice that 10 numbers have been printed.

2. Truly Randomizing - The Randomize Statement

After you run the program once you have the values in the Immediate window. Run the program again and compare the first 10 numbers with the last 10 numbers. Notice a similarity? The Rnd function has a predetermined set of numbers that it shows every time call the rnd function. So every time you start your app, it starts from the beginning showing the same numbers again. How do you avoid this? The Randomize statement makes the Rnd function generate truly random numbers.

TIP : Don't keep using the randomize statement because then it loses it's meaning... Use it only once, right before you start creating random numbers the first time.

TIP : You also have the optional number after in the randomize statement. That number will cause the numbers to be generated randomly but based on that number. So Randomize 2 will always return the same numbers. This can be used in encryption algorithms

Comment from VB help :

Randomize uses number to initialize the Rnd function's random-number generator, giving it a new seed value. If you omit number, the value returned by the system timer is used as the new seed value.

If Randomize is not used, the Rnd function (with no arguments) uses the same number as a seed the first time it is called, and thereafter uses the last generated number as a seed value.

Note : To repeat sequences of random numbers, call Rnd with a negative argument immediately before using Randomize with a numeric argument. Using Randomize with the same value for number does not repeat the previous sequence.

VB Code:
`Private Sub Form_Load()    Randomize    Dim i As Integer    For i = 1 To 10        Debug.Print Rnd    NextEnd Sub`

Now that we added the Randomize statement you can see that every time you run the application, different numbers are produced. If on the other hand you do this :

VB Code:
`Private Sub Form_Load()    Randomize 8    Dim i As Integer    For i = 1 To 10        Debug.Print Rnd    NextEnd Sub`

you'll notice that the same numbers are generated (the encryption I was saying)...

3. The million dollar question...

... or the most commonly asked question is : "How can I generate a number between 2 other numbers?"
The main problem with this is that many people haven't realised that the Rnd function returns a value less than 1 BUT greater than or equal to zero (0<=Rnd<1). So since most people think that the Rnd function can generate the number 1, the algorithms they use are incorrect. The correct way is this :

VB Code:
`Int((upperbound - lowerbound + 1) * Rnd + lowerbound)`

Which can easily be put into a function :

VB Code:
`Private Function RandomInteger(Lowerbound As Integer, Upperbound As Integer) As Integer    RandomInteger = Int((Upperbound - Lowerbound + 1) * Rnd + Lowerbound)End Function`

and an example of using it is :

VB Code:
`Private Function RandomInteger(Lowerbound As Integer, Upperbound As Integer) As Integer    RandomInteger = Int((Upperbound - Lowerbound + 1) * Rnd + Lowerbound)End Function Private Sub Form_Load()    Randomize 'Just once to start getting random numbers    MsgBox RandomInteger(1, 52)End Sub`

The code above would be used most of the times for a card game, to draw a card at random. If we set Lowerbound=1 and Upperbound=6 then we would have ourselves dice rolling code

4. Series Of Unique Random Numbers

The next most popular question is "How to create unique series of random numbers (doesn't have duplicates). Usually this is used for card games or dice rolling games. There are two ways of doing it. In theory both will work, but there is a major advantage of one way as you will see soon

1st option (most common) :
Follow these steps :
1) Generate a random number
2) Store it in an array
3) Generate another random number
4) Compare it with the other elements of the array
5) If it exists then generate another random number and goto step 4, if it doesn't exist add it to the array
6) Repeat as many times as needed steps 3-5

An example code would be this :

VB Code:
`Option Explicit 'Force variable declaration Private Sub Form_Load()    Dim Ar(1 To 100) As Integer 'The array to store it in    Dim i, j As Integer 'Counters for loops    Dim X As Integer 'Variable to store the random generated number    Dim bFound As Boolean 'Boolean to check if the value has been generated before        Randomize 'Just once to ensure that we get random values        For i = 1 To 100        Do 'Start the loop that generates a random number and checks if it has already been generated            X = RandomInteger(1, 100) 'Generate a random number            bFound = False 'Set the boolean to false, if we find the number while searching the array, we'll set it to true which means that we already have that number            For j = 1 To i 'We only need to check up to i (since we haven't put any values in the rest of the array)                If Ar(j) = X Then 'If an item of the arrray is the same as the last generated number                    bFound = True 'Set the boolean to true (it already exists)                    DoEvents 'To not freeze until the looping is done                    Exit For 'Since we found it there is no need to check the rest                End If            Next        Loop Until bFound = False 'If it wasn't found then we'll add it, if it was found then we go back to generating a new number and comparing it with all the items of the array        Ar(i) = X 'Add it to the array    Next        ShowInTextBox Text1, Ar 'Just to print the data and see itEnd Sub Private Function RandomInteger(Lowerbound As Integer, Upperbound As Integer) As Integer 'The random number generator code    RandomInteger = Int((Upperbound - Lowerbound + 1) * Rnd + Lowerbound)End Function Private Sub ShowInTextBox(TB As TextBox, A() As Integer) 'Just a sub to show the data in a textbox    Dim i As Integer        TB.Text = ""        For i = 1 To UBound(A)        TB.Text = TB.Text & CStr(A(i)) & vbCrLf    Next        TB.Text = Left\$(TB.Text, Len(TB.Text) - 2)End Sub`

Unfortunatelly, there is a serious drawback with this method. It all seems fine, but since you are generating a small amount of random numbers then you'll be OK. But if you are trying to generate a large amount of random numbers then theoretically some number might never be generated or at least it could take a while for the number to be generated. This could clearly create an unwanted delay in your program.
I know, the chance is very very small but it will at least delay the process which could cause problems. So here is another option :

2nd option (better) :
You do follow these steps :
1) You create all the numbers you need and store them in a collection
2) Generate a random number
3) Get the element of the collection that has the index of the randomly generated number (Here is the main advantage. You will always get an element since you are generating a number that will always be the index for an element of the array. Since you remove it later, you don't need the time consuming checking )
4) Add that number to the random number array that you want
5) Remove that number from the collection with the list of numbers
6) Repeat 2-5 until the array with the list of numbers is empty

An example code would be this :

VB Code:
`Option Explicit 'Force variable declaration Private Sub Form_Load()    Dim Col As Collection 'The collection we will use to store the numbers    Dim Ar(1 To 100) As Integer 'The array to store the values from the collection    Dim i As Integer 'Counter for loops    Dim X As Integer 'Variable to store the random generated number        Randomize 'Just once to ensure that we get random values        Set Col = New Collection 'Get the collection ready to use        For i = 1 To 100 'The possible numbers that we can have as a result is all the numbers from 1 to 100 so        Col.Add i 'add all the possible numbers to the collection    Next        For i = 1 To 100 'Now to get the 100 numbers we added in the previous loop        X = RandomInteger(1, Col.Count) 'Get a random item from the collection (that exists for sure)        Ar(i) = Col.Item(X) 'Add it to the array        Col.Remove X 'Remove it so we don't add it again    Next        ShowInTextBox Text1, Ar 'Just to print the data and see itEnd Sub Private Function RandomInteger(Lowerbound As Integer, Upperbound As Integer) As Integer 'The random number generator code    RandomInteger = Int((Upperbound - Lowerbound + 1) * Rnd + Lowerbound)End Function Private Sub ShowInTextBox(TB As TextBox, A() As Integer) 'Just a sub to show the data in a textbox    Dim i As Integer        TB.Text = ""        For i = 1 To UBound(A)        TB.Text = TB.Text & CStr(A(i)) & vbCrLf    Next        TB.Text = Left\$(TB.Text, Len(TB.Text) - 2)End Sub`

5. Proof

Now, with the above example it is hard to realise that the second option is better and faster since it's just 100 numbers. In the first case (array) it takes an average of 31-47 milliseconds to complete the task. In the second case it takes 0 milliseconds to complete the task.
So to explain myself better, here is an example with 10000 numbers and a way to track how long was needed to create the list completely :

Array code :

VB Code:
`Option Explicit 'Force variable declaration Private Declare Function GetTickCount Lib "kernel32" () As Long 'The GetTickCount                                                                'function retrieves                                                                'the number of                                                                'milliseconds that                                                                'have elapsed since                                                                'Windows was started. Private Sub Form_Load()    Dim Ar(1 To 10000) As Integer 'The array to store it in    Dim i, j As Integer 'Counters for loops    Dim X As Integer 'Variable to store the random generated number    Dim bFound As Boolean 'Boolean to check if the value has been generated before    Dim S As Long 'Variable to store the number of milliseconds that have elapsed since                  'Windows was started when we begin the task        Randomize 'Just once to ensure that we get random values        S = GetTickCount 'Store the number of milliseconds that have elapsed since Windows was started when we begin the task        For i = 1 To 10000        Do 'Start the loop that generates a random number and checks if it has already been generated            X = RandomInteger(1, 10000) 'Generate a random number            bFound = False 'Set the boolean to false, if we find the number while searching the array, we'll set it to true which means that we already have that number            For j = 1 To i 'We only need to check up to i (since we haven't put any values in the rest of the array)                If Ar(j) = X Then 'If an item of the arrray is the same as the last generated number                    bFound = True 'Set the boolean to true (it already exists)                    DoEvents 'To not freeze until the looping is done                    Exit For 'Since we found it there is no need to check the rest                End If            Next        Loop Until bFound = False 'If it wasn't found then we'll add it, if it was found then we go back to generating a new number and comparing it with all the items of the array        Ar(i) = X 'Add it to the array    Next        'At the end we will subtract the number of milliseconds that had elapsed    'when the task started from the number of milliseconds that have elapsed    'when the task is complete and show it in the form's caption    Me.Caption = GetTickCount - S        ShowInTextBox Text1, Ar 'Just to print the data and see itEnd Sub Private Function RandomInteger(Lowerbound As Integer, Upperbound As Integer) As Integer 'The random number generator code    RandomInteger = Int((Upperbound - Lowerbound + 1) * Rnd + Lowerbound)End Function Private Sub ShowInTextBox(TB As TextBox, A() As Integer) 'Just a sub to show the data in a textbox    Dim i As Integer        TB.Text = ""        For i = 1 To UBound(A)        TB.Text = TB.Text & CStr(A(i)) & vbCrLf        DoEvents    Next        TB.Text = Left\$(TB.Text, Len(TB.Text) - 2)End Sub`

And the collection code :

VB Code:
`Option Explicit 'Force variable declaration Private Declare Function GetTickCount Lib "kernel32" () As Long 'The GetTickCount                                                                'function retrieves                                                                'the number of                                                                'milliseconds that                                                                'have elapsed since                                                                'Windows was started. Private Sub Form_Load()    Dim Col As Collection 'The collection we will use to store the numbers    Dim Ar(1 To 10000) As Integer 'The array to store the values from the collection    Dim i As Integer 'Counter for loops    Dim X As Integer 'Variable to store the random generated number    Dim S As Long 'Variable to store the number of milliseconds that have elapsed since                  'Windows was started when we begin the task        Randomize 'Just once to ensure that we get random values        Set Col = New Collection 'Get the collection ready to use        S = GetTickCount 'Store the number of milliseconds that have elapsed since Windows was started when we begin the task        For i = 1 To 10000 'The possible numbers that we can have as a result is all the numbers from 1 to 100 so        Col.Add i 'add all the possible numbers to the collection    Next        For i = 1 To 10000 'Now to get the 100 numbers we added in the previous loop        X = RandomInteger(1, Col.Count) 'Get a random item from the collection (that exists for sure)        Ar(i) = Col.Item(X) 'Add it to the array        Col.Remove X 'Remove it so we don't add it again    Next            'At the end we will subtract the number of milliseconds that had elapsed    'when the task started from the number of milliseconds that have elapsed    'when the task is complete and show it in the form's caption    Me.Caption = GetTickCount - S        ShowInTextBox Text1, Ar 'Just to print the data and see itEnd Sub Private Function RandomInteger(Lowerbound As Integer, Upperbound As Integer) As Integer 'The random number generator code    RandomInteger = Int((Upperbound - Lowerbound + 1) * Rnd + Lowerbound)End Function Private Sub ShowInTextBox(TB As TextBox, A() As Integer) 'Just a sub to show the data in a textbox    Dim i As Integer        TB.Text = ""        For i = 1 To UBound(A)        TB.Text = TB.Text & CStr(A(i)) & vbCrLf        DoEvents    Next        TB.Text = Left\$(TB.Text, Len(TB.Text) - 2)End Sub`

On my PC, the array code needed 116328 milliseconds which means about 116 seconds which is almost 2 minutes!
The collection code needed 13219 milliseconds which is about 13 seconds!

6. The End

Well, that's all folks!
This is the end of this tutorial about random numbers. I hope you found it useful and helpful so your programming days from now on will be easier.

If you have any questions regarding this tutorial, don't be shy, drop me an e-mail and I'll gladly help you.

Thanks,
manavo

7. The code/files within this thread (submitted: 03-03-2004) have been checked for malware by a moderator.

Disclaimer: This does not necessarily mean that any compiled files (DLL/EXE/OCX etc) are completely safe, but any supplied code does not contain any obvious malware. It also does not imply that code is error free, or that it performs exactly as described.

It is recommended that you manually check any code before running it, and/or use an automated tool such as Source Search by Minnow (available here or here).
If you find any serious issues (ie: the code causes damage or some sort), please contact a moderator of this forum.

Usage of any code/software posted on this forum is at your own risk.

8. Re: Tutorial - Random Numbers

Hi all,

I am new, to this forum and also to VB.Net and I encountered a problem. I need an array that contains 100 random numbers, between 1 and 100. More specifically, the array must contain all the numbers between 1 and 100, but in random order, and I don't know how to do that. Any help would be appreciated.

Thank you.

9. Re: Tutorial - Random Numbers

Welcome to VBForums

This tutorial is actually for Classic VB, not VB.Net.

You should ask in our VB.Net forum, as the methods are different.

10. Re: Tutorial - Random Numbers

Thank you,

I will post it on the VB.Net forum, as you suggested.

11. Re: Tutorial - Random Numbers

Pls Anyone Help Me Here, I Dont Get The Resultz On The Explanation Above

12. Re: Tutorial - Random Numbers

Welcome to VBForums

As the code uses Debug.Print, the numbers will be printed to the Immediate window - if it isn't visible, select it on the View menu.

13. Re: Tutorial - Random Numbers

Your Random Number tutorial is extremly helpful so firstly id like to thank you for posting it.

Would it be possible to change the above code (1st option) so that you could call a list of random numbers one at a time using a command button?

Thanks again

Robert Stevenson

14. Re: Tutorial - Random Numbers

Hi,

This is really very useful for the new vb programmers.

15. Re: Tutorial - Random Numbers

Dim randomnumber As New Random
MessageBox.Show(randomnumber.Next())

only number between 1 and 9

Dim randomnumber As New Random
MessageBox.Show(randomnumber.Next(1,9))

16. Re: Tutorial - Random Numbers

I don't think that is VB6.
Visual Basic.NET and Classic Visual Basic are separated on this forum.
Take a look at the forum index and learn about all the different categories.

17. Re: Tutorial - Random Numbers

Originally Posted by TheBigB
I don't think that is VB6.
Visual Basic.NET and Classic Visual Basic are separated on this forum.
Take a look at the forum index and learn about all the different categories.
It's not it's vb.net! ruipedromachado should have said so in his post. Although, seeing as there is no specification in the original post or the thread title regarding which Visual Basic version is being talked about I can see why he got confused.

18. Re: Tutorial - Random Numbers [VB6 and earlier]

I've added VB6 to the thread title to save that kind of confusion in future.

19. Re: Tutorial - Random Numbers [VB6 and earlier]

how is these possible?
the pc can random, always, the same number... in diferent executions... can anyone explain to me why?

20. Re: Tutorial - Random Numbers [VB6 and earlier]

You need to use the Randomize statement as shown in post #2.

If you want different numbers each time, call Randomize just once at the start of your program (eg: in Form_Load).

If you want to be able to repeat the same set of numbers, call Rnd with a negative argument first, and then Randomize with whatever number you want, eg:
Code:
```Rnd -1
Randomize 2345```

Posting Permissions

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