我正在尝试在用户定义的范围内创建一系列唯一(非重复)随机数。我设法创建随机数,但我得到重复的值。如何确保随机数永远不会重复?
Sub GenerateCodesUser()
Application.ScreenUpdating = False
Worksheets("Users").Activate
Dim MINNUMBER As Long
Dim MAXNUMBER As Long
MINNUMBER = 1000
MAXNUMBER = 9999999
Dim Row As Integer
Dim Number As Long
Dim high As Double
Dim Low As Double
Dim i As Integer
If (CustomCodes.CardNumberMin.Value = "") Then
MsgBox ("Fill Card Number Field!")
Exit Sub
ElseIf (CustomCodes.CardNumberMin.Value < MINNUMBER) Then
MsgBox ("Card Number Value must be equal or higher then" & MINNUMBER)
Exit Sub
End If
If (CustomCodes.CardNumberMax.Value = "") Then
MsgBox ("Fill Card Number Field!")
Exit Sub
ElseIf (CustomCodes.CardNumberMax.Value > MAXNUMBER) Then
MsgBox ("Card Number Value must be equal or higher then " & MAXNUMBER)
Exit Sub
End If
Low = CustomCodes.CardNumberMin.Value
high = CustomCodes.CardNumberMax.Value '<<< CHANGE AS DESIRED
If (Low < 1000) Then
'break
End If
For i = 1 To Cells(1, 1).End(xlToRight).Column
If InStr(Cells(1, i), "CardNumber") Then
Row = 2
While Cells(Row, 1) <> 0
Do
Number = ((high - Low + 1) * Rnd() + Low)
Loop Until Number > Low
Cells(Row, i) = Number
Row = Row + 1
Wend
End If
Next
Application.ScreenUpdating = True
End Sub
答案 0 :(得分:4)
这是一种保证唯一整数随机数的方法。内联注释描述了该方法。
Function UniuqeRandom(Mn As Long, Mx As Long, Sample As Long) As Long()
Dim dat() As Long
Dim i As Long, j As Long
Dim tmp As Long
' Input validation checks here
If Mn > Mx Or Sample > (Mx - Mn + 1) Then
' declare error to suit your needs
Exit Function
End If
' size array to hold all possible values
ReDim dat(0 To Mx - Mn)
' Fill the array
For i = 0 To UBound(dat)
dat(i) = Mn + i
Next
' Shuffle array, unbiased
For i = UBound(dat) To 1 Step -1
tmp = dat(i)
j = Int((i + 1) * Rnd)
dat(i) = dat(j)
dat(j) = tmp
Next
'original biased shuffle
'For i = 0 To UBound(dat)
' tmp = dat(i)
' j = Int((Mx - Mn) * Rnd)
' dat(i) = dat(j)
' dat(j) = tmp
'Next
' Return sample
ReDim Preserve dat(0 To Sample - 1)
UniuqeRandom = dat
End Function
像这样使用
Dim low As Long, high As Long
Dim rng As Range
Dim dat() As Long
Set rng = Range(Cells(1, 1), Cells(1, 1).End(xlToRight))
dat = UniuqeRandom(low, high, rng.Columns.Count)
rng.Offset(1, 0) = dat
注意:请参阅this Wikipedia article regarding shuffle bias
编辑修复了一个偏见来源。 Rnd
(基于32位种子)和Modulo偏差的固有局限仍然存在。
答案 1 :(得分:1)
Function RandLotto(Bottom As Integer, Top As Integer, _
Amount As Integer) As String
Dim iArr As Variant
Dim i As Integer
Dim r As Integer
Dim temp As Integer
Application.Volatile
ReDim iArr(Bottom To Top)
For i = Bottom To Top
iArr(i) = i
Next i
For i = Top To Bottom + 1 Step -1
r = Int(Rnd() * (i - Bottom + 1)) + Bottom
temp = iArr(r)
iArr(r) = iArr(i)
iArr(i) = temp
Next i
For i = Bottom To Bottom + Amount - 1
RandLotto = RandLotto & " " & iArr(i)
Next i
RandLotto = Trim(RandLotto)
End Function
答案 2 :(得分:0)
我看到你有一个接受的答案,但无论如何,这里的价值都是我对这个问题的准备。这个使用布尔函数而不是数值数组。这很简单但很快。它的优点,我不是说是完美的,是长距离数字的有效解决方案,因为你只检查你已经选择并保存的数字,并且不需要一个可能很大的数组来保存数值你已经拒绝,所以它不会因为数组的大小而导致内存问题。
Sub UniqueRandomGenerator()
Dim N As Long, MaxNum As Long, MinNum As Long, Rand As Long, i As Long
MinNum = 1 'Put the input of minimum number here
MaxNum = 100 'Put the input of maximum number here
N = MaxNum - MinNum + 1
ReDim Unique(1 To N, 1 To 1)
For i = 1 To N
Randomize 'I put this inside the loop to make sure of generating "good" random numbers
Do
Rand = Int(MinNum + N * Rnd)
If IsUnique(Rand, Unique) Then Unique(i, 1) = Rand: Exit Do
Loop
Next
Sheet1.[A1].Resize(N) = Unique
End Sub
Function IsUnique(Num As Long, Data As Variant) As Boolean
Dim iFind As Long
On Error GoTo Unique
iFind = Application.WorksheetFunction.Match(Num, Data, 0)
If iFind > 0 Then IsUnique = False: Exit Function
Unique:
IsUnique = True
End Function