Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

weighted random numbers.....woah!

Status
Not open for further replies.

knuckle05

Programmer
Dec 17, 2001
247
0
0
CA
Hi All,

I have no problem generating my random numbers. I'm using the Win API for GetTickCount instead of VB's Randomize and Rnd functions (which stink).

What I would like to do, for example, is if I wanted to generate a random number between 1 & 10 but in certain instances, would like to have a greater chance of hitting a high number, say 8,9 or 10.

So I would like the user to be able to put a "weight" between 1 & 100 (50 would be average) to give the function a greater chance of hitting one of these high numbers

Has anyone done this before?

Any suggestions would be appreciated.
 
You could keep track of the times that you've given out a number. For example if you wanted to pick numbers between 1 and 100 and you wanted the 50 to 100 range to come up 2/3 of the time, the you could do this:

Code:
Do While True

...some exit condition
lngCnt = lngCnt + 1

If lngCnt / 3 > .333 Then
   Keep picking numbers till > 50
End If

Loop

or

Do While True
...some exit condition
If lngCnt / 3 > .333 Then
   Set new Low bound of rnd function
Else
   Restore Low bound of rnd function
End If
Loop
Snaggs
tribesaddict@swbell.net
Life can only be understood backwards; but it must be lived forwards.
 
Snaggs; Actually I thought of that but I'm not sure it will work.

I want to run a process where I will pick 100 numbers between 1 & 1000, but I don't want to ever change my LBound or UBound values, just increase the chance of picking a number in a certain range, but not actually force it...
 
What you can do is set up two ranges and a mapping between the ranges. Consider the following hypothetical. You want to generate a random number 1 to 5, with the following proabilities

1 - 5%
2 - 15%
3 - 20%
4 - 25%
5 - 35%

So generate a number between 1 and 100. Then map down to 1 to 5 with a case statement.
Select Case GeneratedNumber
Case 1 to 5
MappedValue = 1
Case 6 to 20
MappedValue = 2
Case 21 to 40
MappedValue = 3
Case 41 to 65
MappedValue = 4
Case 66 to 100
MappedValue = 5
End Select

Now you mapped values will, over time, approach the selected frequences of your desired proabilities.

Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein


 
Cajun; That seems like a good idea. I'm sure I can use that as a base for what I want to do.

In my original example I'm using static values however I need a solution that is completely dynamic.

I don't really want to choose percentages for each range, just increase the chance of picking higher or lower.

Does it seem logical to multiply my values (somewhere in my logic) by something in the range of 1.00 to 1.99???
 
What I would like to do, for example, is if I wanted to generate a random number between 1 & 10 but in certain instances, would like to have a greater chance of hitting a high number, say 8,9 or 10.

So I would like the user to be able to put a "weight" between 1 & 100 (50 would be average) to give the function a greater chance of hitting one of these high numbers


A few questions - How do you want to determine how much weight to apply to which number? Will the weighting factor always be an increase? What is the criteria for determining you "certain instances"?

Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein


 
Here's an idea. Set up an array 1 to 10 with a min and max value for each element, initially as follows:

1: 1 - 10
2: 11 - 20
3: 21 - 30
..
10: 90 - 100

Generate the random number between 1 and 100. Then find where in the table that number is between the min and max value, and the corresponding array index is the resultant number.

Now apply your weighting formula to adjust the min and max value of this mapping table. Maybe at one of the certain instances it might look like this

6: 51 - 60
7: 61 - 68
8: 69 - 85
9: 86 - 92
10: 93 - 100

we've iincreased the possiblity of an 8, with corresponding decreases in 7, 9, and 10. When that instance is over, reset back to the original values.

Good Luck
--------------
As a circle of light increases so does the circumference of darkness around it. - Albert Einstein


 
Caj; I'm trying to build an automatic scheduler where an Admin user could give preference to certain users, meaning that choice times, such as early times or later times could be automatically given to preferred users.

I was using a simple example before to try to explain the problem. Many criteria will go into this program.

The Admin would apply a weight (any range or percentage) in a higher OR lower manner which would just increase the CHANCE of getting a higher or lower random result. I don't want to FORCE a low or high number, but over a period of time (throughout the process), my targeted numbers would have a higher ratio of being selected....I hope this clarifies a little.
 
There are quite a number of ways to get some numbers more often than others.
1. As a mathematician I would use some function to remap the values to increase the chances. You could use a random function to generate a number between 0 and 1 and use some function to map into 0 to 1 again, but with more emphasis on some range in between. Map to your required range by multiplying and truncating.

Example with more emphasis in the middle

Dim x As Single, r As Integer
x = Rnd() 'or your random function
'.5 emphasizes the middle
'+ (.5^3) to make 0 map to zero
'* (1/.5)^2 to make 1 map to 1
x = (((x - .5)^3) + (.5^3)) * (1/.5)^2
'map result on range 1 to N
r = Fix(N * x) + 1

2. Another option is to use an array say of more indexes than the required number of results (say N) and fill the first N with the numbers 1 to N and the rest with the numbers that should have more chance of being hit. Generate a number between 1 and the higher index and return the array value.

Dim i As Integer, r As Integer
ReDim intResults(N + 5) As Integer
For i = 1 To N
intResults(i) = i
Next i
intResults(N+ 1) = 8
intResults(N+ 2) = 8
intResults(N+ 3) = 9
intResults(N+ 4) = 9
intResults(N+ 5) = 10
r = intResults((N+ 5) * Rnd() + 1)

I hope these are helpfull.
 
ReneGoos; Thanks for your input. I think your first example seems tailored to what I am trying to accomplish. To be quite honest I don't really understand the logic behind the math in this case but I will try to figure it out.

If you can explain your logic I would appreciate it. thanks for your help.

Other suggestions are welcomed
 
The logic of the math is in the derivitive. The derivitive should be nearer zero where you want the emphasis and away from zero where you do not want it. A function with a derivitive higher than or equal zero is easiest to map, so this why I use x^3. You could also use x^5 or higher, a log or an exponential function
 
If I understand correctly, my exponential value should be dynamic in that the further away from zero I want, I should increase my exponent

ex: x^6, x^7 .. x^11 ????
 
You should select just one function and use this for your random values.
For a good idea of what the derivative does you should make a graph of the function, for instance x^3. Following the graph you see that near 0, the graph is hardly going up. Therefore points near 0 map to points nearer zero. Recalculating to your planned range maps these points nearer 1 (if you map from 1 to N) and so points nearer 1 have a higher probability than further away.
A higher exponent has the effect of flattening even more, i.e. a longer range near zero maps near zero and thus remapped near 1.
The point where the graph flattens can be moved by substracting from the x-value: (x-A)^3 flattens in A. In this case add A^3 to map zero to zero.
Check a Calculus book for a proper definition and calculation of derivative or for instance
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top