为什么不能用FOR循环产生不同的随机数?

anyoneokay 2004-07-31 10:49:14
Private Sub Command1_Click()

Dim i As Integer
For i = 1 To 1000
Randomize
ITEM(i) = Int(Rnd * 1000) + 1
List1.AddItem ITEM(i)
Next

End Sub

上面代码产生的随机数会重复,
为什么用了Randomize还会重复?
...全文
680 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
haohaohappy 2004-07-31
  • 打赏
  • 举报
回复
我的意见:
Private Sub Command1_Click()
Dim i As Integer
For i = 1 To 1000
Randomize Timer
ITEM(i) = Int(Rnd * 1000) + 1
List1.AddItem ITEM(i)
Next

End Sub
apple_001 2004-07-31
  • 打赏
  • 举报
回复
反正就是增加随机条件,种子之类的可以提高随机的几率
liujingxiong 2004-07-31
  • 打赏
  • 举报
回复
正解:Randomize后面还要加上Timer,就是Randomize Timer
lsftest 2004-07-31
  • 打赏
  • 举报
回复
上面代码产生的随机数会重复,
为什么用了Randomize还会重复?
====================
你想要的是不是乱序排列1~1000这一千个数?如果是则不应该用你的方法。。。一个简单例子:
Private Sub Command1_Click()
Randomize
Dim i As Integer
Dim k As Integer
Dim temp As Integer
Dim a(1 To 1000) As Integer
For i = 1 To 1000
a(i) = i
Next

For j = 1 To 1000
k = Int(Rnd * 1000) + 1
temp = a(j)
a(j) = a(k)
a(k) = temp
Next

For m = 1 To 1000
List1.AddItem a(m)
Next
End Sub
northwolves 2004-07-31
  • 打赏
  • 举报
回复
也可以用集合实现:
Private Sub Command1_Click()
Dim temp As New Collection, i As Long, tempi As Long
For i = 1 To 1000
temp.Add i
Next
Randomize
For i = 1 To 1000
tempi = Int(Rnd * temp.Count) + 1
List1.AddItem temp(tempi)
temp.Remove tempi
Next
Set temp = Nothing
End Sub
northwolves 2004-07-31
  • 打赏
  • 举报
回复
不会吧
anyoneokay 2004-07-31
  • 打赏
  • 举报
回复
救命啊,上面两种方法还是会重复
northwolves 2004-07-31
  • 打赏
  • 举报
回复
Private Sub Command1_Click()
Dim a(1000) As Integer, i As Integer, temp As Integer
For i = 1 To 1000
a(i) = i
Next
For i = 1000 To 1 Step -1
Randomize
temp = Int(Rnd * i) + 1
List1.AddItem a(temp)
a(temp) = a(i)
Next
End Sub
ryuginka 2004-07-31
  • 打赏
  • 举报
回复
Private Sub Command1_Click()

Dim i As Integer
For i = 1 To 1000
doevents
Randomize
ITEM(i) = Int(Rnd * 1000) + 1
List1.AddItem ITEM(i)
Randomize
Next

End Sub
csdnchenxu 2004-07-31
  • 打赏
  • 举报
回复
楼上的一大堆算法我懒得看了,不过可以告诉楼主,vb提供的随机函数也是根据当前时间
来确定的,所以在for中时间难以改变,随机数也是一样的

办法就是等待一段时间得到不同的时间才行,我记得以前用C写过的就是退出函数得到一个
随机数,然后再调用函数得到一个
KiteGirl 2004-07-31
  • 打赏
  • 举报
回复
Private Sub Command1_Click()
Dim tLongs() As Long

tLongs = LongsSeries(1, 1000, 10) '取10个1到1000以内的不重复随机数。

Text1.Text = ""

For tIndex = LBound(tLongs) To UBound(tLongs)
Text1.Text = tLongs(tIndex) & " " & Text1.Text
Next
End Sub

Function LongsSeries(ByVal pLower As Long, ByVal pUpper As Long, Optional ByVal pGetCount As Long = 0) As Long()
'pLower 下限
'pUpper 上限
'pGetCount 获取数字的数量(默认为0,取全部数列)

Dim tOutLongs() As Long
Dim tOutLongs_Readys() As Boolean

Dim tAbsLength As Long
Dim tAbsCount As Long

tAbsLength = pUpper - pLower
tAbsCount = tAbsLength + 1

ReDim tOutLongs(tAbsLength)
ReDim tOutLongs_Readys(tAbsLength)

Dim tSurIndex As Long
Dim tDesIndex As Long
Dim tGetCount As Long
Dim tTempValue As Long

If pGetCount Then
tGetCount = pGetCount - 1
End If
If (tGetCount > tAbsLength) Or (Not CBool(pGetCount)) Then tGetCount = tAbsLength

Randomize Timer

For tSurIndex = 0 To tGetCount

tDesIndex = Int(Rnd * tAbsCount)

If Not tOutLongs_Readys(tSurIndex) Then
tOutLongs(tSurIndex) = tSurIndex + pLower
tOutLongs_Readys(tSurIndex) = True
End If

If Not tOutLongs_Readys(tDesIndex) Then
tOutLongs(tDesIndex) = tDesIndex + pLower
tOutLongs_Readys(tDesIndex) = True
End If

tTempValue = tOutLongs(tSurIndex)
tOutLongs(tSurIndex) = tOutLongs(tDesIndex)
tOutLongs(tDesIndex) = tTempValue

Next

ReDim Preserve tOutLongs(tGetCount)

LongsSeries = tOutLongs()
End Function
electricperi 2004-07-31
  • 打赏
  • 举报
回复
伪随机数算法就这个毛病。
初始值都是默认的同一个数所以算出来的序列都一样。
要不停的变种子,就是那个Timer
它返回从午夜到现在经过的秒数
自然每一时刻都不一样了
带进去做为初始值才可以得到真正的随机数

PS:学QB时看到的


====生成不重复的随机数====================================================
Const nMax = 150
Dim a(nMax) As Integer

Randomize Timer

For i = 1 To nMax
reCount = False
k = Int(Rnd * nMax)

For j = 1 To i - 1
If k = a(j) Then reCount = True: Exit For
Next j

If reCount = True Then
i = i - 1
Else
a(i) = k
'Any other you want to do.
End If

Next i



就是觉得效率有点低,大家评价一下。
KiteGirl 2004-07-31
  • 打赏
  • 举报
回复
热法的要点是:

以ItemReady数组来表示Item每个元素的初始化情况。在使用前判断它是否被初始化过,如果没有,则初始化为访问下标。这样就省略了初始化的步骤,如果你是在1000个元素里取1000个数则没有优势,但如果你是在100000个元素里取10个数,那么优势就很明显了。





KiteGirl 2004-07-31
  • 打赏
  • 举报
回复
你可以尝试我的“热”法,

Private Sub command1_click1()
dim i as integer, t as integer, k as integer
dim Item(1 to 1000) as integer
dim ItemReady(1 to 1000) as Boolean
for i=1 to 100 '假设你只取100个数字,如果是1000个则写为1000。
t=int(rnd*1000)
if Not ItemReady(t) Then Item(t)=t : ItemReady(t)=true
if Not ItemReady(i) Then Item(i)=i + 1 : ItemReady(i)=true
k=Item(i)
Item(i)=Item(t)
Item(j)=k
next
End Sub
anyoneokay 2004-07-31
  • 打赏
  • 举报
回复
严重感谢各位,我调试了一下.

正确的答案分为两个步骤是:
1.首先用一个for循环,将1到1000的值赋给一个数组Item()
2.然后,再用一个For循环,每次循环产生一个随机数t=int(rnd*1000)+1,让此随机数作为
Item()数组的下标,并与Item(i)交换即可产生不重复的1000个随机数.

也就是说,让随机数产生一个下标,随机交换这1000个数的两个数,打乱1000个数的顺序.
因为交换位置的还是这1000个数,所以不会产生重复.

Private Sub command1_click1()
dim i as integer, t as integer, k as integer
dim Item(1 to 1000) as integer
for i=1 to 1000
Item(i)=i
next
for i=1 to 1000
t=int(rnd*1000)+1
k=Item(i)
Item(i)=Item(t)
Item(j)=k
next
End Sub
laisiwei 2004-07-31
  • 打赏
  • 举报
回复
观察中……
Geo_Cra 2004-07-31
  • 打赏
  • 举报
回复
我是来学习的,算法啊,USACO上面的题目都不大会做了,今天花了30分钟才搞定一道简单的!的题目……廉颇老矣!
zyl910 2004-07-31
  • 打赏
  • 举报
回复
小仙妹!
好久不见了
你好像一直是只管算法的贴子啊


==========================
昏倒,又有一个打错了

For I=[last] To [start] step -1
idx=Int(rnd()*(Idx-[start]+1))+[start]
T=N(I):N(I)=N(idx):N(idx)=T '交换N(I)和N(idx)
Next

[start]:下界
[last]:上界

“idx=Int(rnd()*(Idx-[start]+1))+[start]”的意义是在[start,idx]的范围内产生索引,这样可以在一定程度避免重复问题

刚才KiteGirl(小仙妹)贴的“热”法通过设置标志数组彻底解决了重复问题。缺点是多占了点内存
KiteGirl 2004-07-31
  • 打赏
  • 举报
回复
首先,取Sl可以避免问题的复杂化。

当(Ng-1) < Sl情况下,不是所有的Nv都能被访问到。所以我改进了混排方式。只将前Ng个元素做交换,这样仅保证前Ng个元素排列是随机的。

在访问Nv通过Nr断定这个Nv是不是已经被初始化过值,如果没有则先初始化。

这样,改进后的混排叫做“热”法。原来那个方法戏称“冷”法。

两个方法缺点在于:如果St到Se范围太宽,则数组可能装不下。如果这样的话,我还有一个“虚拟数组”方法解决。可以在任意数值范围内取N个随机不重复排列(前提是N是内存可以接受的)。
KiteGirl 2004-07-31
  • 打赏
  • 举报
回复
哈哈!分兄真是严谨之人,学习!其实我也是偷个小懒而已。上面的算法是“冷”的,现在来个“热”的。

St = 开始
Se = 结束
Sl = Se - St '取相对范围
Ng = 输出数

Dim Nv() As Long '数值
Dim Nr() As Boolean 'Ready表

ReDim Nv(0 To Sl)
ReDim Nr(0 To Sl)

Randomize Timer

For Is=0 To Ng-1
Id=Int(rnd * Sl)

If Not Nr(Is) Then Nv(Is) = Is + St : Nr(Is) = True
If Not Nr(Id) Then Nv(Id) = Id + St : Nr(Id) = True

Vt=Nv(Is):Nv(Is)=Nv(Id):Nv(Id)=Vt '交换N(Is)和N(Id)
Next

Nv(0 To Ng-1)是随机排列。
加载更多回复(8)

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧