views:

322

answers:

8

Is it possible to use rand() or any other pseudo-random generator to pick out random numbers, but have it be more likely that it will pick certain numbers that the user feeds it? In other words, is there a way, with rand() or something else, to pick a pseudo random number, but be able to adjust the odds of getting certain outcomes, and how do you do that if it is possible.

BTW, I'm just asking how to change the numbers that rand() outputs, not how to get the user input.

+7  A: 

Well, your question is a bit vague... but if you wanted to pick a number from 0-100 but with a bias for (say) 43 and 27, you could pick a number in the range [0, 102] and map 101 to 43 and 102 to 27. It will really depend on how much bias you want to put in, what your range is etc.

Jon Skeet
How about this: If the user says so, I want to make it twice as likely that that number will come up, and if they say so, it could be half as likely to come up
Regan
@Regan - the general idea in Jon's answer is that you make a list of numbers, in which you put multiple copies of numbers according to how much you want to favour them. So maybe the numbers 1-10 would appear once, the numbers 11 to 20 would appear twice each, and the numbers 21 to 30 would appear four times each. The list now contains 70 numbers, so you pick one of those 70 at random (unbiased). The bias then occurs simply because some numbers appear in multiple places. You'd be twice as likely to get 25 as you would 15, and half as likely to get 5 as you would 15.
Daniel Earwicker
+3  A: 

You want a mapping function between uniform density of rand() and the probability density that you desire. The mapping function can be done lots of different ways.

hotpaw2
this seems like the best way IMHO because it allows for arbitrary biases
Professor_Calculus
"The mapping function can be done in lots of different ways", such as...
Regan
hotpaw2
+2  A: 

You can certainly use any random number generator to skew the results. Example in C#, since I don't know objective-c syntax. I assume that rand() return a number tween 0 and 1, 0 inclusive and 1 exclusive. It should be quite easy to understand the idear and convert the code to any other language.

 /// <summary>
 /// Dice roll with a double chance of rolling a 6.
 /// </summary>
 int SkewedDiceRoll()
 {
     // Set diceRool to a value from 1 to 7.
     int diceRool = Math.Floor(7 * rand()) + 1;

     // Treat a value of 7 as a 6.
     if (diceRoll == 7)
     {
         diceRoll = 6;
     }

     return diceRoll;
 }
Jan Aagaard
A: 

By definition the output of a random number generator is random, which means that each number is equally likely to occur next (1/10 chance) and you should not be able to affect the outcome.

Of-course, a pseudo-random generator creates an output that will always follow the same pattern for a given input seed. So if you know the seed, then you may have some idea of the output sequence. You can, of-course, use the modulus operator to play around with the set of numbers being output from the generator (eg. %5 + 2 to generate numbers from 2 to 7).

Simon Ellis
Maybe it's just that I don't see it, but, how does this help the OP?
thyrgle
I agree, I don't really know what this has to do with my question
Regan
Sorry, mis-read the Q.
Simon Ellis
"Random" does not necessarily imply "equally likely". Or in other words: a random numbers need not be [uniformly distributed](http://en.wikipedia.org/wiki/Uniform_distribution_(continuous%29), they can be in other distributions as well, for example in [normal distribution](http://en.wikipedia.org/wiki/Normal_distribution).
Joachim Sauer
+1  A: 

This is not too difficult..

simply create an array of all possible numbers, then pad the array with extra numbers of which you want to result more often.

ie:

array('1',1','1','1','2','3','4','4');

Obviously when you query that array, it will call "1" the most, followed by "4"

Kevin
One thing to keep in mind though is that arrays are not declared that way in Objective-C but, I think you have a good point.
thyrgle
yeah, I'm a php guy. But the principal is the same.
Kevin
@Kevin: using strings for storing integers is nasty even when using PHP.
Daniel
A: 

In addition to what Kevin suggested, you could have your regular group of numbers (the wide range) chopped into a number of smaller ranges, and have the RNG pick from the ranges you find favorable. You could access these ranges in a particular order, or, you can access them in some random order (but I can assume this wouldn't be what you want.) Since you're using manually specified ranges to be accessed within the wide range of elements, you're likely to see the numbers you want pop up more than others. Of course, this is just how I'd approach it, and it may not seem all that rational.

Good luck.

Mr_Spock
A: 

You can use the follwing trick This example has a 50 percent chance of producing one of your 'favourite' numbers

int[] highlyProbable = new int[]{...};

public int biasedRand() {
    double rand = rand();
    if (rand < 0.5) {
        return highlyProbable[(int)(highlyProbable.length * rand())];
    } else {
        return (int)YOUR_RANGE * rand();
    }
}
d-live
A: 

In other words, is there a way, with rand() or something else, to pick a pseudo random number, but be able to adjust the odds of getting certain outcomes, and how do you do that if it is possible.

For simplicity sake, let's use the drand48() which returns "values uniformly distributed over the interval [0.0,1.0)".

To make the values close to one more likely to appear, apply skew function log2():

log2( drand48() + 1.0 );  // +1 since log2() in is [0.0, 1.0) for values in [1.0, 2.0)

To make the values close to zero more likely to appear, use the e.g. exp():

(exp(drand48()) - 1.0) * (1/(M_E-1.0));  // exp(0)=1, exp(1)=e

Generally you need to crate a function which would map the uniformly distributed values from the random function into values which are distributed differently, non-uniformly.

Dummy00001