Stuipd simple calculation which I can´t slove - RE OPEN

Discussion in 'Plugin Development' started by Eistee², Oct 18, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    Eistee²

    Hello ,
    I want to make a percentage calculation with Math.random
    My aim is to pick one of these item by her percentage
    Code:
    1:40%
    2:20%
    3:40%
    and I dont know how I can slove this q.q

    so I have 40% chance to get 1 or 3 but only 20% to get 2

    I add every Percentage and then I make a random nummber between 0 and the Max Percentage (100% here)

    but now my problem is when 2 percentages are similar or the last percentage is the highst
    would be nice if someone could help me q.q

    Sorry for my bad english
     
  2. Offline

    hakelimopu

    Code:
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
     
    public class WeightedGenerator<T> {
        private Map<T,Integer> table = new HashMap<T,Integer>();
        private Integer totalWeight = 0;
        public void setWeight(T key,Integer weight){
            if(weight<0) weight=0;
            totalWeight-=getWeight(key);
            table.put(key,weight);
            totalWeight+=getWeight(key);
        }
        public Integer getWeight(T key){
            if(table.containsKey(key)){
                return table.get(key);
            }else{
                return 0;
            }
        }
        public T generate(Random generator){
            T result = null;
            Iterator<T> iterator = table.keySet().iterator();
            Integer generated = generator.nextInt(totalWeight);
            while(generated>=0 && iterator.hasNext()){
                result = iterator.next();
                generated -= getWeight(result);
            }
            return result;
        }
       
    }
    And to use this for your particular application:

    Code:
    WeightedGenerator<Integer> generator = new WeightedGenerator<Integer>();
    generator.setWeight(1,40);
    generator.setWeight(2,20);
    generator.setWeight(3,40);
    generator.generate(new Random());
     
    ferrybig likes this.
  3. Offline

    coldandtired

    Generate your random number based on the total. Use 1 higher than the total to include 0, or shift the value up one if not.

    Loop through the possible values (40, 20, 40) and add them together. When the generated number is lower use that value.

    Code:
    int n = new Random().nextInt(total) + 1; //100, possible n = 1 to 100
    int count = 0;
    for (int i : values) //40, 20, 40
    {
      count += i; // count will be 40, then 60, then 100
      if (n <= count) break; // will break when n = 1 to 40 on the first value, 41 to 60 on the second, and 61 to 100 on the third
    }
    
     
    Eistee² likes this.
  4. Offline

    Eistee²


    I may want to add more than this tree Items and i cant rewrite it than but thanks :)

    Thanks this looks good an nearly than mine (so i wasen´t complet wrong *_*)
    Big thanks ! :)
     
  5. Offline

    hakelimopu

    You can use the WeightedGenerator to generate any combination you like. I was simply showing the equivalent of what you were asking for in the OP. If you had 4 items each with 25%, you'd set the weight for 1,2,3,4 all at 25. Or anything else you wanted. It is a complete general case solution.
     
    Eistee² and Comphenix like this.
  6. Offline

    andf54

    Quick lesson in generics:

    class WeightedGenerator<T> means T can be anything you want. T is determined when you construct the instance.

    WeightedGenerator<WublyWoblyBits> generator = new WeightedGenerator<WublyWoblyBits>();
    generator.setWeight(new WublyWoblyBits(7),40);
    generator.setWeight(new WublyWoblyBits("herpaderp"),20);
    generator.setWeight(new WublyWoblyBits(":L"),40);
    WublyWoblyBits bits = generator.generate(new Random());
     
    Eistee² likes this.
  7. Offline

    Eistee²

    Okay thanks will keep this in my mind!:)
     
  8. Offline

    Eistee²

    Hello , I use the WeightedGenerator to creat my randoms , now my problem is that when I have a double percentage wich is very low like 0.5%
    Code:
    Random Armor
    ItemID;ArmorPack
    chance;2.5%
     
    Pumpkin
    ItemID;86
    chance;70%
     
    Diamond
    ItemID;264
    chance;0.5%
    .....
    it will never take the Diamond.....
    I know its because the " generated -= getWeight(result);" but don´t know how to slove this :(
    (I want that the WeightedGenerator works with doubles like 0,05 or 0,5 ...)

    Would be nice if some on could help me :)
    Code:
        public T generate(Random generator)
        {
            T result = null;
            Iterator<T> iterator = table.keySet().iterator();
            Double generated = generator.nextDouble()*totalWeight;
            while(generated>=0 && iterator.hasNext())
            {
                result = iterator.next();
                generated -= getWeight(result);
            }
            return result;
        }
     
  9. Offline

    Eistee²

  10. chance al "Integer" to "Double" and "int" to "double"
    double has a higer precision
     
  11. Offline

    Eistee²

    I have :/
    Code:
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Random;
     
    public class WeightedGenerator<T>
    {
        private Map<T,Double> table = new HashMap<T,Double>();
        private Double totalWeight = (double) 0;
       
        public void setWeight(T key,Double weight)
        {
            if(weight<0) weight=(double) 0;
           
           
            totalWeight-=getWeight(key);
            table.put(key,weight);
            totalWeight+=getWeight(key);
        }
       
        public Double getWeight(T key)
        {
            if(table.containsKey(key))
            {
                return table.get(key);
            }
            else
            {
                return (double) 0;
            }
        }
       
        public T generate(Random generator)
        {
            T result = null;
            Iterator<T> iterator = table.keySet().iterator();
            Double generated = generator.nextDouble()*totalWeight;
            while(generated>=0 && iterator.hasNext())
            {
                result = iterator.next();
                generated -= getWeight(result);
            }
            return result;
        }
       
      public int size()
      {
          return table.size();
      }
     
      public void clear()
      {
          totalWeight = (double) 0;
          table.clear();
      }
    }
    but when I add a while slope which only break when the result is an Item with a chance under 1% the server crashes :/
     
  12. may I see where you implement this code, as the while statement in this code should break after there are more loops than items are
     
  13. Offline

    Eistee²

    I allready delete this code I but I think it was:

    Code:
        public T generate(Random generator)
        {
            int count = 0;
            T result = null;
        while(getWeight(result) > 1)
    {
            Iterator<T> iterator = table.keySet().iterator();
            Double generated = generator.nextDouble()*totalWeight;
            while(generated>=0 && iterator.hasNext())
            {
                result = iterator.next();
                generated -= getWeight(result);
            }
    count++;
    }
    System.out.println(count);
            return result;
        }
     
  14. if you used the code as in the example, then it worked perfectly
     
  15. Offline

    Eistee²

    Tested again (a with a bit changed code)

    Code:
            while(true)
            {
                Double generated = generator.nextDouble()*totalWeight;
               
                while(generated>=0 && iterator1.hasNext())
                {
                    result = iterator1.next();
                    generated -= getWeight(result);
                }
                count++;
                result1 = result;
                if(getWeight(result1) < 1)
                {
                    break;
                }
            }
            System.out.println(count + " " + result);
    But it always print "2" as count (I think because it only gives 2 items) but I really don't know why :/
     
  16. is there a reason why you can use the code that was posted earlier?
     
  17. Offline

    Eistee²

    I have tested both :( same result
     
Thread Status:
Not open for further replies.

Share This Page