javarandom

Do an action with some probability in java


In Java, I am trying to do an action with a probability p. p is a float variable in my code. I came up with this way of doing it:

if( new Random().nextFloat() < p)
  do action

I wanted to confirm if this is the correct way of doing it.


Solution

  • There is a TL;DR at the end.


    From javadocs for nextFloat() (emphasis by me):

    public float nextFloat()

    Returns the next pseudorandom, uniformly distributed float value between 0.0 and 1.0 from this random number generator's sequence.

    If you understand what uniform distribution is, knowing this about nextFloat() is going to be enough for you. Yet I am going to explain a little about uniform distribution.

    In uniform distribution, U(a,b) each number in the interval [a,b], and also all sub-intervals of the same length within [a,b] are equally probable, i.e. they have equal probability.

    uniform

    In the figure, on the left is the PDF, and on the right the CDF for uniform distribution.

    For uniform distribution, the probability of getting a number less than or equal to n, P(x <= n) from the distribution is equal to the number itself (look at the right graph, which is cumulative distribution function for uniform distribution). That is, P(x <= 0.5) = 0.5, P(x <= 0.9) = 0.9. You can learn more about uniform distribution from any good statistics book, or some googling.

    Fitting to your situation:

    Now, probability of getting a number less than or equal to p generated using nextFloat() is equal to p, as nextFloat() returns uniformly distributed number. So, to make an action happen with a probability equal to p all you have to do is:

    if (condition that is true with a probability p) {
        do action
    }
    

    From what is discussed about nextFloat() and uniform distribution, it turns out to be:

    if(randObj.nextFloat() <= p) {
        do action
    }
    

    P.S.: You don't need to create a new Random object each time in your conditional, you can create one, say randObj before your loop, and then invoke its nextFloat() method whenever you want to generate a random number, as I have done in my code.

    Comment by pjs:

    Take a look at the comment on the question by pjs, which is very important and well said. I quote:

    Do not create a new Random object each time, that's not how PRNGs are meant to be used! A single Random object provides a sequence of values with good distributional properties. Multiple Random objects created in rapid succession are 1) computationally expensive, and 2) may have highly correlated initial states, thus producing highly correlated outcomes. Random actually works best when you create a single instance per program and keep drawing from it, unless you really really know what you're doing and have specific reasons for using correlation induction strategies.


    TL;DR

    What you did is almost the right way to do it. Just adding the equal sign after < (to make it <=) is all that's needed, and it doesn't hurt much to leave out the equal sign either!