Forum Moderators: open
am using the following code to write a string of 15 letters ...
For intCounter = 1 To 15
' Generate a random number between 65 and 90.
Randomize
intDecimal = Int((26 * Rnd) + 1) + 96
str = str & Chr(intDecimal)
Next
but it turns out that it is not generating a unique string as i thought it would, they are coming out unique but a great many are duplicates, am i doing something wrong, or is my error entirely elsewhere. thanks
Btw - here is a ASP/vbScript class that I utilize for generating random strings. It returns alpha-numeric strings, but could easily be adapted to only return letters.
Also, as you will see, the CASE statements in vbScript are limiting. If this is adapted to Visual Basic or a SQL Stored Procedure, it can be cleaned up quite a bit by using ranges in the CASEs.
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
' #########################################################################
' clsPwdGenerator
'
' Password Generator Class
'
' This class has one method, CreatePassword, that can be used to generate
' a random password with a variable length consisting of alpha-numeric
' characters.
' #########################################################################
Class clsPwdGeneratorPublic Function CreatePassword(nMinLen, nMaxLen)
Dim i
Dim nLen
Dim sPwd
Dim sChar
sPwd = ""
nLen = (Int(Rnd * ((nMaxLen - nMinLen) + 1))) + nMinLen
For i = 1 To nLen
Do
sChar = RndChar
Loop While (sChar = "o") Or (sChar = "O") Or (sChar = "l")
sPwd = sPwd & sChar
Next
CreatePassword = sPwd
End FunctionPrivate Function RndChar()
Dim nVal
Dim nChar
nVal = Int(Rnd * 62)
Select Case nVal
Case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25
' Returns a lower case letter a-z
nChar = nVal + 97
Case 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
' Returns a digit 0-9
nChar = nVal + 22
Case 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61
' Returns an uppercase letter A-Z
nChar = nVal + 29
End Select
RndChar = Chr(nChar)
End FunctionPrivate Sub Class_Initialize
Randomize
End Sub
End Class
</SCRIPT>
[edited by: john_k at 3:40 pm (utc) on April 8, 2004]
Randomize
For intCounter = 1 To 15
' Generate a random number between 65 and 90.
intDecimal = Int((26 * Rnd) + 1) + 96
str = str & Chr(intDecimal)
Next
so far seems to work, eg just ran it a few times with no dupes, whereas before it was beginning to produce a dupe almost every time - as it had already generated 20,000 uniques.
is this what you meant? will it continue to produce unique numbers, the total number will be around 1 million at some point, i should think this should be ok, of course i check for dupes but it slows it down to keep regenerating on a dupe.
will it continue to produce unique numbers
No. It will produce random numbers.
If you want guaranteed unique numbers (but in a random order), then you will need another means.
You could use a GUID (globally unique identifier), or you could simply extract all or part of the current time and date and then add that on to the random number you are generating.
If you are using SQL Server, you have two options:
- Use an Identity column. If you don't want to ever get small numbers, then just set the initial seed to something other than 1 (which is the default).
- Otherwise you can create a column with the "Is GUID" property.
Other DBs have similar options.
To convert time and date elements to numbers, use the Now function and strip out non-numeric characters. You can also use the Second, Minute, Hour, Day, Month, and Year functions.
Once you have reasonably small increment of time, then append a random string to the end of it. You should still check for duplicates, but there should be a lot fewer collisions. And more importantly, the rate of collisions should remain stable. (with your current method, the rate will climb as you store more values)