我正在编写一个程序来证明生日悖论'。
For i = 0 To (pnum - 1)
days(i) = rnd(h:=365)
Next
它为1到365之间的每个i
(days(i))
生成一个随机数,函数为:
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
当我在for循环中添加一个断点并手动完成它时,它工作正常,但如果我 只需运行该程序,它就会在天(I)中的每个插槽中放入相同的随机数。
任何想法为什么?
数字生成现在正在运行,但在使用断点进行调试时,程序的工作方式仍然不同。
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
这是整个代码。它的作用是从集合中搜索两个匹配的随机数。整个事情重复100次,它应该计算结果,但它只输出0或100。
答案 0 :(得分:4)
这是重写的功能。
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
从Random的文档中,“默认种子值是从系统时钟派生的,并且具有有限的分辨率。因此,通过调用默认构造函数紧密连续创建的不同随机对象将具有相同的默认种子值,因此,将产生相同的随机数集 ...“
这就是你遇到问题的原因。我还更改了函数的名称,因为它与旧的Rnd方法匹配。
答案 1 :(得分:3)
即使已经给出了一个有效的解决方案,我想解释“为什么” 你的代码没有按照你期望的方式运行。
当涉及到经典计算时,没有真正随机的数字。
Random类根据seed value
生成一系列数字
如果不将此种子值传递给构造函数,则会将系统时间作为种子。
Random
类的构造函数允许您指定要使用的seed value
。
请考虑以下方法:
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
此方法将seed和maximum作为参数,然后创建
具有指定值作为其种子的Random
的实例。
每次使用“seed”和“max”的相同值调用此方法时 无论方法调用之间有多长时间,它都会输出完全相同的数据。
Public Sub Run()
For i As Integer = 0 To 4
PrintRandomNumbers(215668468, 365)
Console.WriteLine()
Thread.Sleep(1000)
Next
End Sub
在我的系统上,这将输出以下内容:
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
我在示例中添加了对Thread.Sleep的调用,以表明它不是时间敏感的
在您的系统上应该生成其他数字,但是对于每次迭代,输出都是相同的。
使用Random
类生成一组不同的随机数的唯一方法
是提供不同的种子,最小和/或最大。
在您的代码中,您在非常紧密的循环中创建了Random
类的新实例
代码执行得如此之快,以至于每次迭代都取seed
值
从系统时间完全相同,结果产生了一组生成的数字
是完全相同的。
将Random
类生成的数字视为无穷无尽的数字序列
在循环的每次迭代中,您创建了一个新实例并获取了第一个数字
那是生成的。在上面的示例数据的情况下,意味着值'3223',
所以你的数组的每个元素都被设置为'3223'
其他成员提供的解决方案在这里起作用,因为他们只有
创建Random
类的单个实例并一遍又一遍地重复使用它
结果,在循环的每次迭代中,他们从无限序列中得到下一个数字。
要做的一件事就是你应该永远记住Random
不是随机的。
答案 2 :(得分:0)
以下代码将帮助您生成最多365个随机数。使用for循环我只在消息框中显示五个,您可以通过增加for循环的限制来扩展它们。
Dim rnd As Random = New Random()
For i As Integer = 0 To 5
MsgBox(rnd.Next(365).ToString)
Next