tags:

views:

513

answers:

13

This is more of a maths/general programming question, but I am programming with PHP is that makes a difference.

I think the easiest way to explain is with an example.

If the range is between 1 and 10.

I want to generate a number that is between 1 an 10 but is more likely lower than high.

The only way I can think is generate an array with 10 elements equal to 1, 9 elements equal to 2, 8 elements equal to 3.....1 element equal to 10. Then generate a random number based on the number of elements.

The trouble is I am potentially dealing with 1 - 100000 and that array would be ridiculously big.

So how best to do it?

+11  A: 

Generate a number between 1 and foo(n), where foo runs an algorithm over n (e.g. a logarithmic function). Then reverse foo() on the result.

David Dorward
+4  A: 

Generate number n which is 0 <= n < 1, multiply it by itself, than multiply by x, run floor on it and add 1. Sorry I used php toooo long ago to write code in it

tig
@Zano, because he is squaring a number less than 1, the number group at the lower end of the range
murgatroid99
@murgatroid99: Of course, I didn't pay attention on the < 1. *Note to self:* don't play with the baby while commenting SO answers
Zano
+3  A: 

You could do

$rand = floor(100000 * (rand(0, 1)*rand(0, 1)));

Or something along these lines

b8b8j
+2  A: 

I think this may be what you're looking for :

Random by weight

DrunkenBeard
A: 

What you need to do is generate a random number over a greater interval (preferably floating point), and map that into [1,10] in a nonuniform way. Exactly what way depends on how much more likely you want a 1 to be than a 9 or 10.

For C language solutions, see these libraries. You may find use for this in PHP.

Pontus Gagge
+18  A: 

Generate a random number between 0 and a random number!

Tim
Clever. I like it. :)
Chris
But it is inefficient. It requires generating two random numbers ;)
nikic
@nikic: You generate a random number in 1 to n twice, which means 2log(n) bits of randomness. For the distribution in the question, this is optimal, as 2log(n) = log(n^2).
ShreevatsaR
This does give a declining probability but it is not the same as is generated by the algorithm presented in the question. Instead it gives a probability of sum(1/i:n)/n where n is the max and i is the integer in question.
frankc
Output graphics (density) in http://a.imageshack.us/img710/8336/rndrnd.png ... for the faithless :D
belisarius
+3  A: 

There are basically two (or more?) ways to map uniform density to any distribution function: Inverse transformation sampling and Rejection sampling. I think in your case you should use the former.

nikic
A: 

Generally speaking, it looks like you want to draw a random number from a Poisson distribution rather than the [uniform distribution](http://en.wikipedia.org/wiki/Uniform_distribution_(continuous)). On the wiki page cited above there is a section which specifically states how you can use the continuous distribution to generate a pseudo-Poisson distribution... check it out. Note that you may want to test different values of λ to ensure the distribution works as you want it to.

eykanal
+2  A: 

Quick and simple:

rand(1, rand(1, n))
Andy
Its a nice simple solution... but I found that it sometimes results in 0. It should be rand(1,rand(1,n). Thanks :)
Pablo
Bah humbug. Fixed :)
Andy
A: 

It depends on what distribution you want to have exactly, i.e., what number should appear with what probability.

For instance, for even n you could do the following: generate one integer random number x between 1 and n/2 and generate a second number between 1 and n+1. If y > x you generate x otherwise you generate n-x+1. This should give you the distribution in your example.

maschka
A: 

recursive randomization

tdtje
A: 

I think this should give the requested distribution:

Generate a random number in the range 1 .. x. Generate another one in the range 1 .. x+1. Return the minimum of the two.

Accipitridae
A: 
frankc