Why is this random number generation code not working?

I am writing a program to confirm the "Birthday Paradox".

    For i = 0 To (pnum - 1)
        days(i) = rnd(h:=365)
    Next

      

It generates a random number for everyone i

(days(i))

between 1 and 365, function:

    Private Function rnd(h As Integer)
    Dim num As Integer
    Dim rnum As Random
    rnum = New Random
    num = rnum.Next(1, h)
    Return num
    End Function

      

When I add a breakpoint in the for loop and look at it manually, it works fine, but if I just run the program, it puts the same random number in every interval in days (I).

Any ideas why?


Generation count works now, but the program still works differently when debugging with breakpoints.

Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim prc As Integer

    For r As Integer = 1 To 100
        Dim pnum As Integer = Val(TextBox1.Text) ''Number of people
        Dim days(pnum - 1) As Integer

        Dim rnd As Random = New Random()
        For i As Integer = 0 To (pnum - 1)
            days(i) = rnd.Next(365)
        Next


        Dim count As Integer = 0
        Dim inc As Integer = 0


        Do

            For inc = (count + 1) To (pnum - 1)
                If count = (pnum - 1) Then
                    Exit For
                End If
                If days(count) = days(inc) Then
                    prc += 1 ''Match found
                    Exit Do
                End If
            Next
            If count = (pnum - 1) Then
                Exit Do
            End If
            count += 1
        Loop

    Next

    MsgBox(prc)
End Sub
End Class

      

That's all the code. It searches for two matching random numbers from the set. This all repeats 100 times and it should count the results, but instead it only outputs 0 or 100.

+3


source to share


3 answers


The function has been rewritten here.

Public Shared rnum As New Random 'only one needed per application

Private Function myRand(h As Integer) As Integer
    Dim num As Integer
    num = rnum.Next(1, h) 'note maxValue is exclusive
    Return num
End Function

      



From the documentation for Random, "The initial default is inferred from the system clock and has a finite resolution. As a result, different random objects that are created in close sequence by calling the default constructor will have the same initial default and will therefore produce identical sets random numbers ... "

This is why you have a problem. I also changed the name of the function because it matches the old Rnd method.

+4


source


Even though a working solution has been given, I would like to explain "WHY"
your code did not behave as you expected.

When it comes to classical computing, there is no such thing as a truly random number.

The Random class generates a series of numbers based on a. seed value


When you don't pass this seed to the constructor, it will take system time as a seed.

The class constructor Random

lets you specify seed value

which one will be used.

Consider the following method:

Private Sub PrintRandomNumbers(seed As Integer, max As Integer)
    Dim rnd = New Random(seed)

    For i As Integer = 0 To 9
        Console.Write("{0} ", rnd.Next(1, max))
    Next
End Sub

      

This method takes seeds and maximum as parameters and then
instantiates an instance Random

with the specified value as its seed.

Every time you call this method with the same values ​​for "seed" and "max",
it will return accurate data, no matter how long it takes between method calls.

Public Sub Run()
    For i As Integer = 0 To 4
        PrintRandomNumbers(215668468, 365)
        Console.WriteLine()
        Thread.Sleep(1000)
    Next
End Sub

      



On my system, this will output the following:

3223 2031 3014 1473 92 2612 1652 62 811 2103
3223 2031 3014 1473 92 2612 1652 62 811 2103
3223 2031 3014 1473 92 2612 1652 62 811 2103
3223 2031 3014 1473 92 2612 1652 62 811 2103
3223 2031 3014 1473 92 2612 1652 62 811 2103

      

I added a call to Thread.Sleep to show you that it is not time sensitive.
Different numbers should have been generated on your system, but the output will be the same for each iteration.

The only way to generate a different set of random numbers with a class Random


is to provide a different seed, min and / or max.

In your code, you've created a new instance of the class Random

in a very tight loop.
The code is executed so quickly that for each iteration the value seed

taken
from the system time was exactly the same, and as a result, the set of generated numbers was identical.

Think of the numbers generated by the class Random

as an infinite sequence of numbers.
At each iteration of the loop, you created a new instance and took the first number
that was generated. Which in the case of the above given example means "3223",
so every element of your array would be set to "3223"

The solutions suggested by other contributors work because they only
create one instance of the class Random

and reuse it over and over again.
As a result, at each iteration of the loop, they got the next number from the infinite sequence.

One thing to take away from you is something that you must always remember is Random

not random.

+3


source


The following code will help you generate random numbers up to 365. Using a for loop I only display five of them in the message box, you can expand them by increasing the limit of the for loop.

    Dim rnd As Random = New Random()
    For i As Integer = 0 To 5
    MsgBox(rnd.Next(365).ToString)
    Next

      

0


source







All Articles