Why isn't this Random number generation code working?

最后都变了- 提交于 2020-01-14 19:22:07

问题


I'm writing a program for proving the 'Birthday Paradox'.

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

It generates a random number for every i (days(i)) between 1 and 365, the function is:

    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 go through it manually, it works fine, but if I just run the program, it puts the same random number in every slot in days(I).

Any ideas why?


The number generation is working now, but the program is still working differently while 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 the whole code. What it does is searching for two matching random numbers from the set. The whole thing repeats 100 times and it should count the results, but instead it only outputs 0 or 100.


回答1:


Here is the function re-written.

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 default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers..."

This is why you are having the problem mentioned. I also changed the name of the function because it matches the old Rnd method.




回答2:


Even though a working solution has been given, I'd like to explain "WHY"
your code did not behave the way you expected it to.

When it comes down to classic 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 do not pass this seed value to the constructor it will take the system time as seed.

The constructor for the Random class allows you to specify the seed value to 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 the seed and maximum as parameters and then creates
an instance of the Random with the specified value as its seed.

Every time you call this method with the same values for 'seed' and 'max'
it will output the exact same data, no matter how much time between the 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 the example to show you it is not time sensitive.
On your system other numbers should be generated, but for every iteration the output will be the same.

The only way to generate a different set of random numbers with the Random class
is to provide a different seed, minimum and/or maximum.

In your code, you created a new instance of the Random class in a very tight loop.
The code executed so fast that for every iteration the seed value 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 Random class as an endless sequence of numbers.
In every iteration of your loop you created a new instance and took the first number
that was generated. Which in case of the example data above, meant the value '3223',
so every element of your array would have been set to '3223'

The solutions provided by the other members here work because they only
create a single instance of the Random class and re-use it over and over again.
As a result, in every iteration of the loop, they got the next number from the endless sequence.

One thing to take away from this is that you should always remember Random isn't random.




回答3:


The following code will help you to generate random numbers up to 365.using the for loop i displayed only five among them in message box you can extend 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


来源:https://stackoverflow.com/questions/25105640/why-isnt-this-random-number-generation-code-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!