43

I was curious to know, how do I implement probability in Java? For example, if the chances of a variable showing is 1/25, then how would I implement that? Or any other probability? Please point me in the general direction.

River
  • 8,585
  • 14
  • 54
  • 67
Jeel Shah
  • 3,274
  • 17
  • 47
  • 68

5 Answers5

73

You'd use Random to generate a random number, then test it against a literal to match the probability you're trying to achieve.

So given:

boolean val = new Random().nextInt(25)==0;

val will have a 1/25 probability of being true (since nextInt() has an even probability of returning any number starting at 0 and up to, but not including, 25.)

You would of course have to import java.util.Random; as well.

As pointed out below, if you're getting more than one random number it'd be more efficient to reuse the Random object rather than recreating it all the time:

Random rand = new Random();
boolean val = rand.nextInt(25)==0;

..

boolean val2 = rand.nextInt(25)==0;
Michael Berry
  • 70,193
  • 21
  • 157
  • 216
36

Generally you use a random number generator. Most of those return a number in the interval [0,1[ so you would then check whether that number is < 0.04 or not.

if( new Random().nextDouble() < 0.04 ) {  //you might want to cache the Random instance
   //we hit the 1/25 ( 4% ) case.
}

Or

if( Math.random() < 0.04 ) {
  //we hit the 1/25 ( 4% ) case.
}

Note that there are multiple random number generators that have different properties, but for simple applications the Random class should be sufficient.

Edit: I changed the condition from <= to < because the upper boundary of the random number is exlusive, i.e. the largest returned value will still be < 1.0. Hence x <= 0.04 would actually be slightly more than a 4% chance, while x < 0.04 would be accurate (or as accurate as floating point math can be).

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • 3
    In the general case, this solution using rand.nextDouble() is better than the accepted answer, as it can apply to any arbitrary probability (rather than just to 1/x for a given integer x). For example, if your target probability is 33.5%, there is no simple, clean solution using rand.nextInt(). – shiri Aug 29 '16 at 20:01
  • 1
    @shiri that depends due to potential precision issues. Using integers you could create an integer between 0 and 1000 and check for the value being below 335. – Thomas Sep 05 '16 at 07:43
  • 2
    agreed, I suppose it comes down to a matter of preference. When I think of probabilities I tend to think in terms of numbers in the range of [0,1], so I find nextDouble() <= X to be cleaner. – shiri Sep 07 '16 at 16:53
  • does it make sense to use <= (instead of <) given that == is misleading in floats due to precision? – Hilikus Oct 21 '21 at 21:46
  • @Hilikus for small values the precision would be good enough for `==` but you can do it how you like. Whether the boundary is included or not should not make a huge difference. – Thomas Oct 22 '21 at 11:59
  • What if a chance is `0%`? Your code would still consider it a success, because it's `<=` – parsecer Oct 15 '22 at 00:25
  • @parsecer you're right albeit I'd not agree with your argument of a 0% chance. I'd not even test probability for anything that has 0% chance because that will _alway_ fail. However, `<` instead of `<=` is more accurate as the upper boundary is exclusive. – Thomas Oct 16 '22 at 20:37
  • @Thomas I solve my task of simulating a random event occurring with k * 100% probability (represented by variable `k` - in rage `0 - 1`): `int randomNumber = new Random().nextInt(100); double diceRoll = randomNumber / (double) 100; if (diceRoll < k) {//event occurred}` Therefore for `k = 0`, `randomNumber` would always be greater or equal to `0`, thus event won't occur. For `k = 1`, `randomNumber` will always be less than that, thus even would occur – parsecer Oct 17 '22 at 18:31
  • @parsecer fair enough. You code looks like it would be part of a game and I assume probability can change so you'd not know whether it would be 0% beforehand. Btw, your code seems not to have fractional percentages as `randomNumber` is an integer and thus it could be optimized to do integer comparisons, i.e. `k * 100` would probably need to be recalculated less often than `randomNumber / 100`. – Thomas Oct 18 '22 at 06:06
6

Since 1.7 it's better to use (in concurrent environment at least):

ThreadLocalRandom.current().nextInt(25) == 0

Javadoc

A random number generator isolated to the current thread. Like the global Random generator used by the Math class, a ThreadLocalRandom is initialized with an internally generated seed that may not otherwise be modified. When applicable, use of ThreadLocalRandom rather than shared Random objects in concurrent programs will typically encounter much less overhead and contention. Use of ThreadLocalRandom is particularly appropriate when multiple tasks (for example, each a ForkJoinTask) use random numbers in parallel in thread pools. Usages of this class should typically be of the form: ThreadLocalRandom.current().nextX(...) (where X is Int, Long, etc). When all usages are of this form, it is never possible to accidently share a ThreadLocalRandom across multiple threads.

This class also provides additional commonly used bounded random generation methods.

Wald
  • 69
  • 1
  • 2
5

Java has a class called java.util.Random which can generate random numbers. If you want something to happen with probability 1/25, simply generate a random number between 1 and 25 (or 0 and 24 inclusive) and check whether that number is equal to 1.

if(new java.util.Random().nextInt(25)==0){
    //Do something.
}
Jack Edmonds
  • 31,931
  • 18
  • 65
  • 77
3

Maybe you can implement this with generating random numbers.

  Random rn = new Random();
    double d = rn.nextDouble();     // random value in range 0.0 - 1.0
    if(d<=0.04){
    doSomeThing();
    }
narek.gevorgyan
  • 4,165
  • 5
  • 32
  • 52