# VBForums UtilityBank > UtilityBank - Tutorials >  Tutorial - Random Numbers  [VB6 and earlier]

## manavo11

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
    Next
End Sub

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

----------


## manavo11

*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  :Wink: 

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
    Next
End 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
    Next
End Sub

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

----------


## manavo11

*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  :Smilie:

----------


## manavo11

*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  :Wink: 

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 it
End 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  :Wink:  )
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 it
End 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

----------


## manavo11

*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 it
End 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 it
End 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!

----------


## manavo11

*The End*

Well, that's all folks!  :Big Grin: 
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.  :Alien Frog: 

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

----------


## si_the_geek

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._

----------


## Vatyk

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.

----------


## si_the_geek

Welcome to VBForums  :wave: 

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

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

----------


## Vatyk

Thank you,

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

----------


## NARL

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

----------


## si_the_geek

Welcome to VBForums  :wave: 

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.

----------


## Stevenson00719

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

----------


## PVB_Great

Hi, 

      This is really very useful for the new vb programmers.

----------


## ruipedromachado

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))

----------


## 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.

----------


## Nightwalker83

> 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.

----------


## si_the_geek

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

----------


## joaquim

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

----------


## si_the_geek

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:


```
Rnd -1
Randomize 2345
```

----------

