代码一
Imports System.IO
Public Class Form1
Dim frequency() As Integer = New Integer(6) {}
Sub DisplayPic(ByVal picdie As PictureBox)
Dim randomobject As New Random()
Dim face As Integer = randomobject.Next(1, 7)
picdie.Image = Image.FromFile(Directory.GetCurrentDirectory & "/images/die" & face & ".png")
frequency(face) += 1
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub btnRoll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRoll.Click
txtBoxOutput.Text = Nothing
Dim TOTAL As Double = 0
txtBoxOutput.Text = "Face" & vbTab & vbTab & "frequency" & vbTab & "Percent" & vbCrLf
DisplayPic(picBox1)
DisplayPic(picBox2)
DisplayPic(picBox3)
DisplayPic(picBox4)
DisplayPic(picBox5)
DisplayPic(picBox6)
DisplayPic(picBox7)
DisplayPic(picBox8)
DisplayPic(picBox9)
DisplayPic(picBox10)
DisplayPic(picBox11)
DisplayPic(picBox12)
For i As Integer = 1 To frequency.GetUpperBound(0)
TOTAL = TOTAL + frequency(i)
Next
For x As Integer = 1 To 6 Step 1
txtBoxOutput.Text &= x & vbTab & vbTab & frequency(x) & vbTab & vbTab & String.Format("{0:n}", frequency(x) / TOTAL * 100) & "%" & vbCrLf
Next
End Sub
End Class
代码二
Imports System.IO
Public Class Form1
Dim randomobject As New Random()
Dim frequency() As Integer = New Integer(6) {}
Sub DisplayPic(ByVal picdie As PictureBox)
Dim face As Integer = randomobject.Next(1, 7)
picdie.Image = Image.FromFile(Directory.GetCurrentDirectory & "/images/die" & face & ".png")
frequency(face) += 1
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub btnRoll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRoll.Click
txtBoxOutput.Text = Nothing
Dim TOTAL As Double = 0
txtBoxOutput.Text = "Face" & vbTab & vbTab & "frequency" & vbTab & "Percent" & vbCrLf
DisplayPic(picBox1)
DisplayPic(picBox2)
DisplayPic(picBox3)
DisplayPic(picBox4)
DisplayPic(picBox5)
DisplayPic(picBox6)
DisplayPic(picBox7)
DisplayPic(picBox8)
DisplayPic(picBox9)
DisplayPic(picBox10)
DisplayPic(picBox11)
DisplayPic(picBox12)
For i As Integer = 1 To frequency.GetUpperBound(0)
TOTAL = TOTAL + frequency(i)
Next
For x As Integer = 1 To 6 Step 1
txtBoxOutput.Text &= x & vbTab & vbTab & frequency(x) & vbTab & vbTab & String.Format("{0:n}", frequency(x) / TOTAL * 100) & "%" & vbCrLf
Next
End Sub
End Class
思考:
比较上面两段代码,唯一的区别就是“Dim randomobject As New Random()”处的位置,代码一位于DisplayPic()方法体内,在代码二中在类中,换句话在代码一种randomobject是局部变量,代码二中是全局变量,从结果中很明确的看出,代码一会导致random(seed)中的seed趋向一致从而产生同样的随机数,代码二则不会导致seed一致,随机数的分布是均匀的。
MSDN上的备注:
伪随机数是以相同的概率从一组有限的数字中选取的。所选数字并不具有完全的随机性,因为它们是用一种确定的数学算法选择的,但是从实用的角度而言,其随机程度已足够了。Random 类的当前实现是基于 Donald E. Knuth 的减随机数生成器算法的。有关更多信息,请参见 D. E. Knuth.“The Art of Computer Programming, volume 2: Seminumerical Algorithms”。Addison-Wesley,Reading,MA,second edition,1981。
随机数的生成是从种子值开始。如果反复使用同一个种子,就会生成相同的数字系列。产生不同序列的一种方法是使种子值与时间相关,从而对于 Random 的每个新实例,都会产生不同的系列。默认情况下,Random 类的无参数构造函数使用系统时钟生成其种子值,而参数化构造函数可根据当前时间的刻度数采用 Int32 值。
但由于时钟分辨率有限,频繁地创建不同的 Random 对象会创建出产生相同随机数序列的随机数生成器。通过创建单个而不是多个 Random 对象可以避免此问题。
要提高性能,请创建一个 Random,以便随着时间的推移可以生成很多随机数,而不要重复新建 Random 来生成一个随机数。
例如,要生成适合于创建随机密码的加密安全随机数,请使用从 System.Security.Cryptography..::.RandomNumberGenerator 派生的类,如 System.Security.Cryptography..::.RNGCryptoServiceProvider
解释:
MSDN备注的红字部分很清楚的说明了代码一为何会产生相同的随机数,代码一在方法体内,每一个方法都会创建一个random对象,从而产生相同随机数。而代码二则在方法外面,只创建一个random对象从而避免了相同随机数的尴尬。所以当创建random对象是一定要把它放在方法体外,也就是使它成为全局变量,只创建一次,这样同时显示的不同方法产生的随机数才是真正的“随机”。