|
-
May 15th, 2008, 10:47 AM
#1
Random Number
The following allows you to pick a group random numbers from a range of numbers like -19099 to 107,
or 1 to 52. It returns an array of integers, dim x() as Integer, as the result.
An example:
Dim cards As Integer() = generateRandomNumbers(1, 52, 4) 'returns four random numbers between 1 and 52
cards = generateRandomNumbers(1, 52, 4, False) 'get four more - note the Pool is not cleared
You can also check to see if a number has been selected by using picked:
If picked(an integer goes here) Then doSomething
The following test
generateRandomNumbers(1, 100000, 100000)
took about 100 ms. on my 1.8Ghz laptop.
Many thanks to kleinma for his insights.
Code:
Module RandomNumberGenerator
'
'The following Function's can be used to generate a set of
'unique random numbers in a defined range.
'
'How it works:
'An array of bits, one for each possible number, is created. Initially all bits are set to 0
'Then a loop is started that:
' generate a random number between low and high inclusive
' check bit at random number selected
' - if 1 then selected, skip. if 0 then set it to 1, add number to array, increment count.
' continue loop till requested count is satisfied
'
'usage - generateRandomNumbers(low, high, howmany, new pool, exception)
'where:
' low = lowest number to be generated - negatives allowed
' high = highest number to be generated - negatives allowed
' howmany = how many numbers to generate between low and high inclusive
' new pool = (true / false) start with no numbers selected
' exception = (true / false) if true throw exception else return array of length 0
'
'the pool is all numbers from low to high inclusive e.g low = -3 high = 6
'-3 -2 -1 0 1 2 3 4 5 6
'size of the pool is 10
'
'the following are defined here intentionally
Public theRandomNumbers As New BitArray(1)
Public zeroPt As Integer = 0, genTime As Long, howManyAvail As Integer = 0
'
Public Function generateRandomNumbers _
(ByVal RangeLow As Integer, _
ByVal RangeHigh As Integer, _
ByVal QtyToGenerate As Integer, _
Optional ByVal NewPool As Boolean = True, _
Optional ByVal ExceptionOnError As Boolean = True) As Integer()
Dim LenPool As Integer
Dim TheReturn As Integer() = {} 'zero length return
Dim size As Integer = RangeHigh - RangeLow + 1 'size of pool
Dim GenRndm As New Random, ctHits As Integer = 0, num2Check As Integer, rndSTPW As New Stopwatch
If RangeLow >= RangeHigh Then 'is low greater or equal to high
If ExceptionOnError Then
Throw New System.Exception("Low must be less than High") 'low >= high not allowed
Else
Return TheReturn 'return array of length 0
End If
End If
If QtyToGenerate <= 0 Then 'generate zero or less
If ExceptionOnError Then
Throw New System.Exception("Quantitiy must be greater than zero")
Else
Return TheReturn 'return array of length 0
End If
End If
If size < QtyToGenerate Then
If ExceptionOnError Then
Throw New System.Exception("Quantitiy exceeds number available") 'low = 0 high = 2 gen =5????
Else
Return TheReturn 'return array of length 0
End If
End If
rndSTPW.Reset() : rndSTPW.Start() 'start the clock
' determine pool size
If Math.Abs(RangeLow) > Math.Abs(RangeHigh) Then LenPool = Math.Abs(RangeLow) Else LenPool = Math.Abs(RangeHigh)
If LenPool < Math.Abs(RangeHigh - RangeLow) Then LenPool = Math.Abs(RangeHigh - RangeLow)
theRandomNumbers.Length = LenPool + 1 'set size of random pool
If NewPool Then 'is this new pool
theRandomNumbers.SetAll(False) 'yes, set all to not selected
howManyAvail = size 'set how many available
Else 're-using the same pool
If howManyAvail < QtyToGenerate Then 'generate less than available
If ExceptionOnError Then 'yes
Throw New System.Exception("Quantitiy exceeds number available")
Else
Array.Resize(TheReturn, 0) 'return array of length 0
Return TheReturn
End If
End If
End If
Array.Resize(TheReturn, QtyToGenerate) 'set return size
'set zero point to handle any case {-3 -2 -1 0 1 2 3}
Select Case True
Case RangeLow >= 0
'0 1 2 3 low=0 high=3
zeroPt = 0
Case RangeHigh <= 0
'-3 -2 -1 0 low=-3 high=0
zeroPt = LenPool
Case RangeLow < 0
'-2 -1 0 1 low=-2 high=1
zeroPt = Math.Abs(RangeLow)
End Select
'finally, generate the random numbers
Do
num2Check = GenRndm.Next(RangeLow, RangeHigh + 1) 'get a random number
If Not theRandomNumbers(num2Check + zeroPt) Then 'picked previously
theRandomNumbers.Set(num2Check + zeroPt, True) 'no, mark it picked
TheReturn(ctHits) = num2Check 'add to return
ctHits += 1 'increment count
If ctHits >= QtyToGenerate Then Exit Do
End If
Loop
rndSTPW.Stop() 'stop the clock
howManyAvail -= ctHits
genTime = rndSTPW.ElapsedMilliseconds 'store time to generate numbers
Return TheReturn
End Function
Public Function Picked(ByVal number As Integer) As Boolean
If number > theRandomNumbers.Length - 1 Then Return False
If theRandomNumbers(number + zeroPt) Then Return True Else Return False
End Function
End Module
Last edited by dbasnett; May 31st, 2008 at 08:40 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|