Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weighted randomness in Java [duplicate]

Tags:

java

random

In Java, given n Items, each with weight w, how does one choose a random Item from the collection with a chance equal to w?

Assume each weight is a double from 0.0 to 1.0, and that the weights in the collection sum to 1. Item.getWeight() returns the Item's weight.

like image 250
Matthew Piziak Avatar asked Jul 18 '11 18:07

Matthew Piziak


People also ask

How do you do weighted random in Java?

Create weights based on your method of choice. Add the weights beginning with 0.0 while adding the weight of the last element to your running weight counter. Then you just have to generate rand = new Random(); num = rand. nextDouble() * count to get a valid number.

How do you generate a random number between 1000 and 9999 in Java?

int randomNumber = ( int )( Math. random() * 9999 ); if( randomNumber <= 1000 ) { randomNumber = randomNumber + 1000; Math. random() is a method that generates a random number through a formula.

How do you generate a random number between 1 to 10 in Java?

For example, to generate a random number between 1 and 10, we can do it like below. ThreadLocalRandom random = ThreadLocalRandom. current(); int rand = random. nextInt(1, 11);


1 Answers

2020 Update (interesting how this got 37 upvotes with a glaring bug in the 2011 version below):

  • Fix the impossibility to select the last item when Math.random() yields a number very close to 1.0, and we are unlucky with floating point precision: random index -1 would be the result, which is obviously wrong.
  • Some code compaction
  • Less variable names used
Item[] items = ...;  // Compute the total weight of all items together. // This can be skipped of course if sum is already 1. double totalWeight = 0.0; for (Item i : items) {     totalWeight += i.getWeight(); }  // Now choose a random item. int idx = 0; for (double r = Math.random() * totalWeight; idx < items.length - 1; ++idx) {     r -= items[idx].getWeight();     if (r <= 0.0) break; } Item myRandomItem = items[idx]; 

2011 version (for comparison left in):

Item[] items = ...;  // Compute the total weight of all items together double totalWeight = 0.0d; for (Item i : items) {     totalWeight += i.getWeight(); } // Now choose a random item int randomIndex = -1; double random = Math.random() * totalWeight; for (int i = 0; i < items.length; ++i) {     random -= items[i].getWeight();     if (random <= 0.0d)     {         randomIndex = i;         break;     } } Item myRandomItem = items[randomIndex]; 

like image 127
Martijn Courteaux Avatar answered Sep 22 '22 21:09

Martijn Courteaux