Public Function GetRandomNum(sngBegin As Single, sngEnd As Single) As Single Debug.Assert sngEnd > sngBegin Randomize GetRandomNum = (sngEnd - sngBegin) * Rnd + sngBegin End FunctionPublic Sub GetRnds(ByVal bytNum As Byte, ByVal lngSum As Long, ByRef lngRnds() As Long) Dim i As Byte, j As Byte Dim lngCurSum As Long
Debug.Assert lngSum > 0
lngCurSum = lngSum ReDim lngRnds(bytNum - 1) For i = 0 To bytNum - 2 lngRnds(i) = GetRandomNum(0, CSng(lngCurSum)) lngCurSum = lngCurSum - lngRnds(i) Next i If i < bytNum - 2 Then For j = i To bytNum - 1 lngRnds(j) = 0 Next j Else lngRnds(bytNum - 1) = lngCurSum End If End SubPublic Sub test() Dim rr() As Long Dim i As Byte Call GetRnds(4, 100, rr) For i = 0 To UBound(rr) Debug.Print i & ":" & rr(i) Next i Erase rr End Sub
上面的代码有误,作废。 Public Function GetRandomNum(sngBegin As Single, sngEnd As Single) As Single Debug.Assert sngEnd > sngBegin Randomize GetRandomNum = (sngEnd - sngBegin) * Rnd + sngBegin End FunctionPublic Sub GetRnds(ByVal bytNum As Byte, ByVal lngSum As Long, ByRef lngRnds() As Long) Dim i As Byte, j As Byte Dim lngCurSum As Long
Debug.Assert lngSum > 0
lngCurSum = lngSum ReDim lngRnds(bytNum - 1) For i = 0 To bytNum - 2 lngRnds(i) = GetRandomNum(0, CSng(lngCurSum)) lngCurSum = lngCurSum - lngRnds(i) If lngCurSum = 0 Then Exit For Next i If i < bytNum - 2 Then For j = i To bytNum - 1 lngRnds(j) = 0 Next j Else lngRnds(bytNum - 1) = lngCurSum End If End SubPublic Sub test() Dim rr() As Long Dim i As Byte Call GetRnds(4, 100, rr) For i = 0 To UBound(rr) Debug.Print i & ":" & rr(i) Next i Erase rr End Sub
只能给出“貌似”随机数。我的想法是这样:1 将“定数”除以 N,取整,得 M1...Mn 。注意,现在 M 都相等,且 M * N 可能小于“定数”(模差)。 2 取 N - 1 个随机数,其最大值是 Mi (Rnd() * Mi, i = 1 ... N - 1,如果不允许随机数 = 0,可令其最大值为 Mi - 1)。从 Mi 中减去随机数 Ri,加到 Mi+1 上。 3 最后再求一个随机数 Rnd() * N + 1,把模差加到 MR 上。 4 再求一轮 N - 1 个随机数,Rnd() * N, Rnd() * (N - 1) ... Rnd() * 2,把 M 逐一抽取,重新排序。
Debug.Assert sngEnd > sngBegin
Randomize
GetRandomNum = (sngEnd - sngBegin) * Rnd + sngBegin
End FunctionPublic Sub GetRnds(ByVal bytNum As Byte, ByVal lngSum As Long, ByRef lngRnds() As Long)
Dim i As Byte, j As Byte
Dim lngCurSum As Long
Debug.Assert lngSum > 0
lngCurSum = lngSum
ReDim lngRnds(bytNum - 1)
For i = 0 To bytNum - 2
lngRnds(i) = GetRandomNum(0, CSng(lngCurSum))
lngCurSum = lngCurSum - lngRnds(i) Next i
If i < bytNum - 2 Then
For j = i To bytNum - 1
lngRnds(j) = 0
Next j
Else
lngRnds(bytNum - 1) = lngCurSum
End If
End SubPublic Sub test()
Dim rr() As Long
Dim i As Byte
Call GetRnds(4, 100, rr)
For i = 0 To UBound(rr)
Debug.Print i & ":" & rr(i)
Next i
Erase rr
End Sub
Public Function GetRandomNum(sngBegin As Single, sngEnd As Single) As Single
Debug.Assert sngEnd > sngBegin
Randomize
GetRandomNum = (sngEnd - sngBegin) * Rnd + sngBegin
End FunctionPublic Sub GetRnds(ByVal bytNum As Byte, ByVal lngSum As Long, ByRef lngRnds() As Long)
Dim i As Byte, j As Byte
Dim lngCurSum As Long
Debug.Assert lngSum > 0
lngCurSum = lngSum
ReDim lngRnds(bytNum - 1)
For i = 0 To bytNum - 2
lngRnds(i) = GetRandomNum(0, CSng(lngCurSum))
lngCurSum = lngCurSum - lngRnds(i)
If lngCurSum = 0 Then Exit For
Next i
If i < bytNum - 2 Then
For j = i To bytNum - 1
lngRnds(j) = 0
Next j
Else
lngRnds(bytNum - 1) = lngCurSum
End If
End SubPublic Sub test()
Dim rr() As Long
Dim i As Byte
Call GetRnds(4, 100, rr)
For i = 0 To UBound(rr)
Debug.Print i & ":" & rr(i)
Next i
Erase rr
End Sub
只能给出“貌似”随机数。我的想法是这样:1 将“定数”除以 N,取整,得 M1...Mn 。注意,现在 M 都相等,且 M * N 可能小于“定数”(模差)。
2 取 N - 1 个随机数,其最大值是 Mi (Rnd() * Mi, i = 1 ... N - 1,如果不允许随机数 = 0,可令其最大值为 Mi - 1)。从 Mi 中减去随机数 Ri,加到 Mi+1 上。
3 最后再求一个随机数 Rnd() * N + 1,把模差加到 MR 上。
4 再求一轮 N - 1 个随机数,Rnd() * N, Rnd() * (N - 1) ... Rnd() * 2,把 M 逐一抽取,重新排序。