Random number in range with a bias.

Discussion in 'Spigot Plugin Development' started by Jonnyo101, Jun 16, 2019.

  1. Hi guys i am wondering if anyone can help me with this..
    I am trying to make a method to generate a random int in a range but with a bias to Higher Or Lower numbers.

    Currently i am using this method to generate a random number
    Code (Java):
    public int randInt(final int n1, final int n2) {
            if (n1 == n2) {
                return n1;
            }

            final int min = n1 > n2 ? n2 : n1;
            final int max = n1 > n2 ? n1 : n2;

            return rand.nextInt(max - min + 1) + min;
        }
    i am looking to have somthing like
    public int randInt(final int n1, final int n2, final float bias)
    So adding a Positive Bias like 3.5 would make higher numbers in the range appear more
    and negative numbers as a bias make lower numbers in the range appear more.
    Where the greater the bias number the more of a effect it has.

    What i was using to do this before was
    Code (Java):
      public int randIntWeightedLow(int max, int min, int rolls){

            int rValue = 100;

            for (int i = 0; i < rolls ; i++) {
                int rand = randInt(min, max);

                if (rand < rValue ){
                    rValue = rand;
                }
            }
           
            return rValue;
        }
    But the problem with this is there is not much control with using int rolls.
    Going from 2 rolls to 4 makes a big difference.

    I am looking for something that can be more fine tuned.

    Any help would be great
     
  2. Try this, you can fine tune the bias variable to make it better suit your needs.
    The lower you set the bias the less impact it has.
    Code (Java):
    private final float bias = 0.5f;
     
    public int randIntWeightedLow(int max, int min, int rolls){
        int rValue = max;

        for(int i = 0; i < rolls ; i++) {
            int rand = randInt(min, max);

            if (rand < rValue)
                rValue -= (rValue - rand) * bias;
        }
     
        return rValue;
    }

    If I were you I'd also rewrite the function to be more efficient.
    Keep in mind I assume max is really the larger number and min the smaller one so you don't need the randInt() function. Also, the bias is a lot harsher this way.
    Code (Java):
    private final float bias = 0.1f;

    public int randIntWeightedLow(int max, int min, int iterations){
        int result = max;
        for(int i = 0; i < iterations; i++)
            result -= (result - rand.nextInt(result - min + 1) + min) * bias;
        return result;
    }
     
    #2 Rappelr, Jun 16, 2019
    Last edited: Jun 16, 2019
  3. Both your methods do not seem to work when testing.. When using
    for (int i = 0; i < 20 ; i++) {
    getLogger().Info_Plain(String.valueOf(Util.RAND_CHANCE.randIntWeightedLow(30, 10, 2)));
    }

    To output 20 random number with a BIAS of 10.0
    I get the output of
    [​IMG]
    As you can see they are not in the range of 30 to 10. Also from i see your adding a bias to the random output.

    What i want it to do it generate a random number in the Min and Max range but with a bias towards the min or max
    Eg say i get 10 random numbers from 1 to 5, and set the bias to 0.5 out of the 10 numbers generated more will be higher then
    If i set the bias to 0.5 more of the numbers will be lower.
    But will always be in the range that is set.

    Also the "Rolls" system was a old way of doing it to make the generated numbers lower.
    The higher the rolls the more likely it would pick a lower random number within the range.

    This rolls i do not want to use as its to precise enough.
     
  4. The bias is a float value, setting it to 1 means no bias, you can only go lower than that. So don't use bias 10.
    As I said, the lower the bias, the less it leans towards the minimum.

    I did a test with 20 rolls, with the fuction like so: randIntWeightedLow(100, 0, 20).
    here is the result variable after every roll:
    Code (YAML):
    result at roll 0: 23
    result at roll 1
    : 7
    result at roll 2
    : 3
    result at roll 3
    : 0
    result at roll 4
    : 0
    result at roll 5
    : 0
    result at roll 6
    : 0
    result at roll 7
    : 0
    result at roll 8
    : 0
    result at roll 9
    : 0
    result at roll 10
    : 0
    result at roll 11
    : 0
    result at roll 12
    : 0
    result at roll 13
    : 0
    result at roll 14
    : 0
    result at roll 15
    : 0
    result at roll 16
    : 0
    result at roll 17
    : 0
    result at roll 18
    : 0
    result at roll 19
    : 0
    Code (YAML):
    result at roll 0: 50
    result at roll 1
    : 47
    result at roll 2
    : 40
    result at roll 3
    : 31
    result at roll 4
    : 29
    result at roll 5
    : 24
    result at roll 6
    : 19
    result at roll 7
    : 8
    result at roll 8
    : 7
    result at roll 9
    : 7
    result at roll 10
    : 4
    result at roll 11
    : 2
    result at roll 12
    : 1
    result at roll 13
    : 1
    result at roll 14
    : 1
    result at roll 15
    : 0
    result at roll 16
    : 0
    result at roll 17
    : 0
    result at roll 18
    : 0
    result at roll 19
    : 0
    Code (YAML):
    result at roll 0: 76
    result at roll 1
    : 55
    result at roll 2
    : 44
    result at roll 3
    : 40
    result at roll 4
    : 33
    result at roll 5
    : 25
    result at roll 6
    : 23
    result at roll 7
    : 21
    result at roll 8
    : 15
    result at roll 9
    : 14
    result at roll 10
    : 13
    result at roll 11
    : 10
    result at roll 12
    : 10
    result at roll 13
    : 7
    result at roll 14
    : 4
    result at roll 15
    : 2
    result at roll 16
    : 1
    result at roll 17
    : 1
    result at roll 18
    : 0
    result at roll 19
    : 0
    Code (YAML):
    result at roll 0: 90
    result at roll 1
    : 82
    result at roll 2
    : 78
    result at roll 3
    : 72
    result at roll 4
    : 69
    result at roll 5
    : 63
    result at roll 6
    : 58
    result at roll 7
    : 53
    result at roll 8
    : 51
    result at roll 9
    : 50
    result at roll 10
    : 49
    result at roll 11
    : 45
    result at roll 12
    : 42
    result at roll 13
    : 40
    result at roll 14
    : 36
    result at roll 15
    : 34
    result at roll 16
    : 32
    result at roll 17
    : 30
    result at roll 18
    : 29
    result at roll 19
    : 26
    Code (YAML):
    result at roll 0: 96
    result at roll 1
    : 94
    result at roll 2
    : 93
    result at roll 3
    : 89
    result at roll 4
    : 86
    result at roll 5
    : 83
    result at roll 6
    : 82
    result at roll 7
    : 80
    result at roll 8
    : 79
    result at roll 9
    : 76
    result at roll 10
    : 75
    result at roll 11
    : 72
    result at roll 12
    : 70
    result at roll 13
    : 68
    result at roll 14
    : 65
    result at roll 15
    : 62
    result at roll 16
    : 59
    result at roll 17
    : 56
    result at roll 18
    : 54
    result at roll 19
    : 52
     
    #4 Rappelr, Jun 16, 2019
    Last edited: Jun 16, 2019
  5. Okay i see thankyou..

    How would i make it so the bias can work the other way Bias high ?
     
  6. Like so, I think i'ts pretty self explanatory.
    Code (Java):
    public int biasRandom(int max, int min, int iterations, boolean upwards) {
        int result = upwards ? min : max;
        for(int i = 0; i < iterations ; i++)
            result += (upwards ? random.nextInt(max - result + 1) : -random.nextInt(result - min + 1)) * bias ;
        return result;
    }