# Random number - no duplicates

Hi!

I have the following code:

dim low, high

Randomize
low = 2
high = 99

Function ran()
ran = Int((high - low + 1) * Rnd()) + low
End Function

The function gives me a random value between 1 and 100. However, I get duplicates...how do I adjust the code to get rid of the duplicate-problem?

The number does not necessarily have to be an integer.

Any ideas much appreciated!
LVL 1
###### Who is Participating?

Commented:
Why not just create an autonumber field in Access and use that?  If you really must create a unique number on your own, you could also combine what you have with some elements of a timestamp to insure that it is unique:

<%
Randomize
Response.Write Month(Now) & Day(Now) & Year(Now) & Hour(Now) & Minute(Now) & Second(Now) & Int((100 - 1 + 1) * Rnd()) + 1
%>
0

IT ConsultantCommented:
What are you using the random codes for? Are you storing them anywhere? in an array or db? If you are, you can do a check to see if it matches before continuing.

Found this code at ASP 101:
http://www.asp101.com/samples/random_number.asp?lowerbound=0&upperbound=100

<%
Dim intLowerBound    ' Lower bound of the random number range
Dim intUpperBound    ' Upper bound of the random number range

Dim intRangeSize     ' Size of the range
Dim sngRandomValue   ' A random value from 0 to intRangeSize
Dim intRandomInteger ' Our final result - random integer to return

' Retrieve lower and upper bound requests if they're there
' o/w set to defaults of 0 and 100
If IsNumeric(Request.QueryString("lowerbound")) Then
intLowerBound = CLng(Request.QueryString("lowerbound"))
Else
intLowerBound = 0
End If

If IsNumeric(Request.QueryString("upperbound")) Then
intUpperBound = CLng(Request.QueryString("upperbound"))

' Add a line to deal with default case of 0 to 0.
' This really isn't neccessary, but I do it so the
' sample doesn't default to generating a number between
' 0 and 0 and always return 0 when no bounds are provided.
If intLowerBound = 0 And intUpperBound = 0 Then intUpperBound = 100
Else
intUpperBound = 100
End If

' Check for people asking for a number from in an inappropriate
' range (ie: 50 to 10) and swap the bounds
If intLowerBound > intUpperBound Then
' I really should've declared a temporary variable for this
' swapping, but I was lazy and this one was already defined
' and I don't use it till later... oh all right I'll do it
' the "right" way... actually even this is bad... I should've
' defined this up top... so sue me... hey it's free code what
' do you want from me?
Dim iTemp
iTemp = intLowerBound
intLowerBound = intUpperBound
intUpperBound = iTemp
End If

' Initialize the random number generator.
' Randomize can actually take parameters telling it how to initialize
' things, but for the most you'll just want to call it without passing
' it anything.
Randomize()

' Generate our random number.
' The Rnd function does most of the work.  It returns a value in the
' range 0 <= value < 1 so to generate a random integer in the specified
' range we need to do some calculation.  Specifically we take the size
' of the range in which we want to generate the number (add 1 so the
' upper bound can be generated!) and then multiply it by our random
' element.  Then to place the value into the correct range of numbers
' we add the lower bound.  Finally we truncate the number leaving us
' with the integer portion which is always somewhere between the
' lower bound and upper bound (inclusively).

' Find range size
intRangeSize = intUpperBound - intLowerBound + 1

' Get a random number from 0 to the size of the range
sngRandomValue = intRangeSize * Rnd()

' Center the range of possible random numbers over the desired result set
sngRandomValue = sngRandomValue + intLowerBound

' Convert our value to an integer
intRandomInteger = Int(sngRandomValue)

' The above 4 lines are equivilent to the popular shorter version
' below.  I split it up so I could indicate what each step is doing.
' intRandomInteger = Int((intUpperBound - intLowerBound + 1) * Rnd + intLowerBound)

' Show out output indicating what we've done and our result.
%>
You asked for a random number between <B><%= intLowerBound %></B> and <B><%= intUpperBound %></B>.<BR>
The computer returned: <B><%= intRandomInteger %></B><BR>

<!-- Build the form for user input -->
<FORM ACTION="random_number.asp" METHOD="get" NAME="frmRandomNumberBounds">

Generate a random number between
<INPUT TYPE="text" NAME="lowerbound" VALUE="<%= intLowerBound %>" SIZE="5" MAXLENGTH="5"></INPUT>
and
<INPUT TYPE="text" NAME="upperbound" VALUE="<%= intUpperBound %>" SIZE="5" MAXLENGTH="5"></INPUT>

<INPUT TYPE="submit"></INPUT>

</FORM>
0

Author Commented:

I removed the Int from the code above which means that I'll get a few decimals. The probability that I get duplicates is low - at least if I only use it for 128 different records.

The problem with duplicates still exists though, it would be fun to know how to solve it.

The value is stored in an access database.
0

Systems architectCommented:
My method is different and less coding.
You define a List with the dimension of elements you need.
You preset all elements in sequence order.
Then you go from first element to last and swap that element with a random element from the List.
That way you know that every element is occuring only once in the List.

0

Author Commented:
Zvonko,

thx for your answer. I am not sure that I understand. Could you give me an example of code?

0

Systems architectCommented:
I tryed to install my IIS and it failed. So I cannot do the tested example.
Show my your code snippet and I wil convert it to standalone VBScript with my random method.
I mean, the upper Ran() definition gives a single shot and cannot know what previous ten or next ten hits will be.
If you need a simelar Ran() function that hits one shot, then you need also a List and let the Ran() function take the next element from the list in the RoundRobin sequence, from first to last and then from first again.

Like this:
dim low, high, r, h, n
dim rNum(99)
Randomize
low = 2
high = 99
For i:=0 to high
rNum(i) = i+1
End For
For i:=0 to high
r = Int(100 * Rnd())
h = rNum(r)
rNum(r) =  rNum(i)
rNum(i) = h
End For

n = 0
Function ran()
ran = rNum(n)
n = n+1
if (n>ubound(rNum)) Then n = 0
End Function

0

Author Commented:
peterxlane,

for a second I actually thought that I had forgotten the most obvious, i.e. using the Autonumber Field. But, luckily, things are a bit more complicated :)

Your idea with the timestamp is great. Thanks!

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.