Weighted randomness Problem

Discussion in 'Spigot Plugin Development' started by MATGR, Jun 6, 2017.

  1. Hi,

    I am making a plugin, I have items with percentages, I want to pick one item randomly according to its percentage.

    For example : Item A = 40%, Item B = 80%
    I have more chances to get Item B than Item A

    Is there any algorithm to solve my problem ?

    Thanks in advance,
     
  2. random integer out of 100, if the result is greater than 40 then return B, otherwise return A.

    Code (Text):
    Random r = new Random();

    int result = r.nextInt(100) //0-99

    if(result > 39) {
    //Item B
    } else {
    //Item A
    }
     
  3. Code (Text):
            double percentage = ThreadLocalRandom.current().nextDouble(1, 100);
           
            if (percentage <= 40.00D) {
                //40% chance etc..
            }
     
  4. ThreadLocalRandom is faster.
     
    • Agree Agree x 1
  5. Don't get a new instance of the Random class every time you need to get some random numbers, use ThreaLocalRandom.current().
    Code (Text):
    if (ThreadLocalRandom.current().nextInt(100) < percentage) {
        //Do something
    }
    The random number will be at least 0 and at most 99. If the percentage is 100, the condition will always be true. If the percentage is 0, the condition will always be false.
    For more posts like this: https://www.spigotmc.org/search/29797554/?q=chances&o=relevance
     
  6. ScarabCoder

    ScarabCoder Retired Resource Staff
    Retired

    If you're hardcoding it, it's pretty simple:
    Code (Text):
    float i = ThreadLocalRandom.current().nextFloat();
    if(i < 0.2){
    //20% chance
    }else if(i < 0.5){
    //30% chance
    }else{
    //50% chance
    }
    If it's from a config or a user set list, my preferred method is to sort the list of possible values by the weight (highest weight first). That way, the weight can be anything (not just a percentage). Then, get a random int from 0 to the sum of all the weights, then loop through all values and check if the random int is <= the weight.
     
  7. I thought that only applies if multiple threads are using the same instance of Random() then contention becomes an issue.
    I guess might as well get in the habit of using it so you don't have to worry about if you end up multithreading.
     
  8. ScarabCoder

    ScarabCoder Retired Resource Staff
    Retired

    It's a better idea to use nextFloat() and use percentages. It's how proper percentages work (0-1).
     
  9. Of course the more accuracy he wants, the more memory he will need to allocate to the value, i.e using int, double, float, long values.
    However in this instance double should be fine for what he's after, heck maybe even int.