VBA編程實現不重復隨機數輸出。VBA裏的隨機函數是RND,在工作表中隨機函數是RAND,壹字之差,可要記好了。RND取值範圍是[0,1),意思是0和1之間的壹個隨機數,包含0,但不包含1。
1、用法
語法:Rnd[(number)]
如果 number 的值是 Randomize 生成
小於 0 ,每次都使用 number 作為隨機數種子得到的相同結果。
大於 0 ,以上壹個隨機數為種子產生下壹個隨機數。
等於 0 ,產生與最近生成的隨機數相同的隨機數。
省略, 以上壹個隨機數為種子產生下壹個隨機數(同大於0)。
說明:
Rnd 函數返回小於 1 但大於或等於 0 的值。
number 的值決定了 Rnd 生成隨機數的方式。
對最初給定的種子都會生成相同的數列,因為每壹次調用 Rnd 函數都用數列中的前壹個數作為下壹個數的種子。
在調用 Rnd 之前,先使用無參數的 Randomize 語句初始化隨機數生成器(若帶參數,則產生由參數對應的壹個特定序列的隨機數),該生成器具有根據系統計時器得到的種子。如果不使用Randomize 語句,那麽每次執行程序時產生的隨機數序列是相同的。
Rnd 後面跟壹個負數時,同樣的參數可以得到完全相同的兩個序列,例如,rnd -1執行後用rnd取1000個隨機數,然後再執行rnd -1,然後再用rnd取1000個隨機數,這1000個隨機數和前面1000個完全相同。為了得到不同的序列,可以用不同的負數,也可以在rnd -1後面執行Randomize number。註意,要得到相同的序列,兩次Randomize後面的number必須相同。這種方法用途之壹就是用於加密和解密。
為了生成某個範圍內的隨機整數,可使用以下公式:
Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
這裏,upperbound 是隨機數範圍的上限,而 lowerbound 則是隨機數範圍的下限。
註意:若想得到重復的隨機數序列,在使用具有數值參數的 Randomize 之前直接調用具有負參數值的 Rnd。使用具有同樣 number 值的 Randomize 是不會得到重復的隨機數序列的。
2、無重復隨機數算法壹
這是最簡單的算法,每產生壹個隨機數,就和已有的比較,如果已經存在,則重新產生。比較適合從壹個大範圍裏面抽出壹小部分數據,比如,從題庫中抽取試題。
[vb]?view plain?copy?print?
' 產生20個1-100之間的不重復隨機數
Public?Sub?RndNumberNoRepeat1()
Dim?RndNumber, temp(20), i, k, Maxrec?As?Integer
Randomize (Timer)?'初始化隨機數生成器
Maxrec = 100
' 從A21開始輸出隨機數
k = 0
Do?While?k < 20
RndNumber = Int(Maxrec * Rnd) + 1
temp(k) = RndNumber
Cells(k + 21, 1) = RndNumber
For?i = 0?To?k - 1
If?temp(i) = RndNumber?Then?Exit?For
Next?i
If?i = k?Then?k = i + 1
'MsgBox "隨機數:" & RndNumber
Loop
End?Sub
3、無重復隨機數算法二
這個算法比較巧妙,需要細細體會,才能知道真諦。這個算法不會重復產生隨機數,但需要壹個占位數組。比較適合輸出範圍之內所有數值的場合,比如,隨機發牌。
[vb]?view plain?copy?print?
' 產生20個1-100之間的不重復隨機數
Sub?RndNumberNoRepeat2()
Dim?RndNumber, TempArray(99), i?As?Integer
Randomize (Timer)?'初始化隨機數生成器
For?i = 0?To?99?'產生包含1-100的不重復的隨機數列
TempArray(i) = i
Next?i
For?i = 99?To?80?Step?-1
RndNumber = Int(i * Rnd)
'從A21開始輸出這些數字
Cells(120 - i, 1) = TempArray(RndNumber) + 1
TempArray(RndNumber) = TempArray(i)
Next?i
End?Sub
4、無重復隨機數算法三
這個算法使用字典對象完成去重復,和第壹個算法差不多,但程序看上去簡潔壹點,嗯,起碼新穎壹點。
[vb]?view plain?copy?print?
' 產生20個1-100之間的不重復隨機數
Sub?RndNumberNoRepeat3()
Dim?d?As?Object?'New Dictionary
Dim?s?As?Integer
Randomize (Timer)?'初始化隨機數生成器
Set?d = CreateObject("Scripting.Dictionary")
Do?Until?d.Count = 20
s = Int(Rnd * 100 + 1)
d(s) =?""
Loop
[a21].Resize(d.Count, 1) = Application.Transpose(d.Keys)
End?Sub
附:VBA中Dictionary對象使用小結
Dim dict
' 創建Dictionary
Set dict = CreateObject("Scripting.Dictionary")
' 增加項目
dict.Add "A", 300
dict.Add "B", 400
dict.Add "C", 500
' 統計項目數
n = dict.Count
' 刪除項目
dict.Remove ("A")
' 判斷字典中是否包含關鍵字
dict.exists ("B")
' 取關鍵字對應的值,註意在使用前需要判斷是否存在key,否則dict中會多出壹條記錄
Value = dict.Item("B")
' 修改關鍵字對應的值,如不存在則創建新的項目
dict.Item("B") = 1000
dict.Item("D") = 800
' 對字典進行循環
k = dict.keys
v = dict.Items
For i = 0 To dict.Count - 1
key = k(i)
Value = v(i)
MsgBox key & Value
Next
' 刪除所有項目
dict.Removeall
實例:
Sub 宏1()Set dic = CreateObject("Scripting.Dictionary") '字典
For i = 1 To 10000
If Not i Like "*4*" Then
dic.Add i, "" '如果不包含“1”
End If
Next
Range("a2").Resize(dic.Count, 1) = Application.WorksheetFunction.Transpose(dic.keys) '從A2單元開始向下放置
End Sub
=========================================================================
又 Tranpose工作表函數的用法實例
'把壹行多列的二維數組轉換成壹維數組
Sub test()
Dim arr, arrt
arr = Range("a1:j1")
arrt = WorksheetFunction.Transpose(WorksheetFunction.Transpose(arr))
Stop
End Sub
首先看看TRANSPOSE函數的基礎用法。官方幫助說明,TRANSPOSE函數可返回轉置單元格區域,即將行單元格區域轉置成列單元格區域,反之亦然。
TRANSPOSE函數語法是:TRANSPOSE(array)
Array參數是需要進行轉置的數組或工作表上的單元格區域。所謂數組的轉置就是,將數組的第壹行作為新數組的第壹列,數組的第二行作為新數組的第二列,以此類推