|
本帖最后由 盗梦 于 2014-7-26 18:05 编辑
有时候,我们需要抽取一些随机数,而且这些随机数不能重复。简单的做法,就是每抽取一次随机数,就把这个随机数和前面抽取出来的比较,如果重复就重新抽取,直到不重复为止。
当这样做的效率很低。需要抽取的数量很大时,这种做法速度相当的慢。
可以这么思考,我们抽取随机数,就好比摇奖。摇出的数字,就取出,不参与下一次摇奖。这样自然而然的就不会重复了。
下面我要讲的算法是利用数组。数组的值是我们要抽取的值,数组的下标就是我们用于随机的数。把这两个分开,就容易实现不重复的效果。
代码如下:
'函数:funcUnSameRnd;
'参数1:要抽取随机数范围的最小值,
'参数2:要抽取随机数范围的最大值,
'参数3:要抽取不重复随机数的个数。
- Public Function funcUnSameRnd(lngLow As Long, lngUp As Long, lngNum As Long)
- '判断要获取的个数
- Dim lngLength As Long
- lngLength = lngUp - lngLow + 1 '获取长度
- If lngNum > lngLength Then lngNum = lngLength '若要获取随机数的个数大于长度,则数量改为最大长度
- If lngNum < 1 Then lngNum = 1 '随机数的个数不能少于1个
- '初始化数组 数组的下标从 0 ~ 最大长度-1,数组的值从 lngLow 到 lngUp
- Dim arr(), i As Integer, iTemp As Long
- ReDim arr(lngLength - 1)
- iTemp = lngLow
- For i = 0 To lngLength - 1
- arr(i) = iTemp
- iTemp = iTemp + 1
- Next
- '抽取随机数
- Randomize '重置随机器
- Dim lngRnd As Long '用于存在返回的随机数
- Dim lngTemp As Long '两个变量调换的中间临时变量
- iTemp = 1
- Do
- '抽取随机数 0 ~ lngLength-1 获取数组下标
- lngRnd = Int(Rnd() * (lngLength - iTemp)) + iTemp - 1 '加上iTemp - 1 是为了跳过前面已经抽取的值,避免覆盖
- '调换值,将抽取到的随机数下标对应的值放到前面,之所以放到前面,是为了方便返回结果
- lngTemp = arr(iTemp - 1)
- arr(iTemp - 1) = arr(lngRnd)
- arr(lngRnd) = lngTemp
- '继续抽取
- iTemp = iTemp + 1
- Loop While iTemp <= lngNum
- '返回结果,截取抽取的随机数个数,Preserve 关键字作用是ReDim重新定义不清除值
- ReDim Preserve arr(lngNum - 1)
- funcUnSameRnd = arr
- End Function
复制代码
这个函数,可以轻松地得到我们想要的结果。测试一下
测试函数:
- Public Function funcTest()
- Dim ar()
- ar = funcUnSameRnd(1, 100, 20) '从1到100中,抽取20个不重复的随机数
- '打印值
- Dim i As Integer
- For i = 0 To UBound(ar)
- Debug.Print "第" & i + 1 & "个随机数:" & ar(i)
- Next
- End Function
复制代码
我们抽取从1到100之间,20个不重复的随机数。
结果如下:
我又测试了,从1到100,抽取100个不重复的随机数,结果完全正确。大家可以自己试一下。
而且,这个函数效率相当高。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|