我们不得不承认这样一个事实:那就是尽管在高级程序语言设计中包含了类似于Random产生随机数之类的方法,但是它产生的随机数并不能满足我们日常的需要,因为它可能重复——设想一下,电子化抽取试题的原理就是根据预定产生的题目数量产生果敢若干个对应的随机数,然后将匹配的试题抽取、排序并打印在试卷上。但是在同一次考试时候不允许同一题目出现重复(尽管这样的概率很低,但是我们绝对不允许这样做!)。所以避免产生重复随机数的方法(产生“真正的随机数”)成了我们必须研究的话题。今天本文就讨论一下。
产生不重复随机数的方法有很多——我倾向于“筛选法”(当然,这个方法是我在学习随机数时候突然想出来的,可能之前就有许多人早就有了这种思想)。 所谓“筛选法”就是根据要产生随机数指定的范围(起始数必须小于终止数),将这些数全部装入一个数组,然后利用系统随机函数(比如 Random )随机产生一个下标,将这个下标对应的数值返回并删除对应的这个数,直到这个数组为空。
下面给出VB.NET和C#对应的代码:
(VB.NET)
Public
NotInheritable
Class TureRandom
Private nums As New ArrayList
Public Sub New(ByVal startnum As Integer, ByVal endnum As Integer)
If (startnum >= endnum) Then
Throw New Exception("对不起,起始数字必须小于结尾数字!")
Else
For i As Integer = startnum To endnum
nums.Add(i)
Next
End If
End Sub
Public Function GetNum() As Integer
If (nums.Count <= 0) Then
Throw New Exception("对不起,指定范围的随机数全部产生过了。")
Else
Randomize()
Dim index As Integer = Rnd() * nums.Count
Dim returnnum As Integer = CType(nums(index), Integer)
nums.RemoveAt(index)
Return returnnum
End If
End Function
End Class
Private nums As New ArrayList
Public Sub New(ByVal startnum As Integer, ByVal endnum As Integer)
If (startnum >= endnum) Then
Throw New Exception("对不起,起始数字必须小于结尾数字!")
Else
For i As Integer = startnum To endnum
nums.Add(i)
Next
End If
End Sub
Public Function GetNum() As Integer
If (nums.Count <= 0) Then
Throw New Exception("对不起,指定范围的随机数全部产生过了。")
Else
Randomize()
Dim index As Integer = Rnd() * nums.Count
Dim returnnum As Integer = CType(nums(index), Integer)
nums.RemoveAt(index)
Return returnnum
End If
End Function
End Class
(C#)
public
sealed
class
TureRandom
{
private ArrayList nums=new ArrayList();
public TureRandom (int startnum, int endnum)
{
if (startnum >= endnum)
throw new Exception("对不起,起始数字必须小于结尾数字!")
else
for (int i=startnum; i<=endnum;++i)
nums.Add(i);
}
public int GetNum()
{
if (nums.Count <= 0) Then
throw new Exception("对不起,指定范围的随机数全部产生过了。")
else
{
Random r = new Random();
int index=(int)(r.NextDouble()*10+1);
int returnnum =(int)(nums[index]);
nums.RemoveAt(index);
return returnnum;
}
}
}
{
private ArrayList nums=new ArrayList();
public TureRandom (int startnum, int endnum)
{
if (startnum >= endnum)
throw new Exception("对不起,起始数字必须小于结尾数字!")
else
for (int i=startnum; i<=endnum;++i)
nums.Add(i);
}
public int GetNum()
{
if (nums.Count <= 0) Then
throw new Exception("对不起,指定范围的随机数全部产生过了。")
else
{
Random r = new Random();
int index=(int)(r.NextDouble()*10+1);
int returnnum =(int)(nums[index]);
nums.RemoveAt(index);
return returnnum;
}
}
}