问题
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