# Random number in range with a bias.

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

1. ### Jonnyo101

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. ### Rappelr

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
Last edited: Jun 16, 2019
3. ### Jonnyo101

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

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. ### Rappelr

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
Last edited: Jun 16, 2019
5. ### Jonnyo101

Okay i see thankyou..

How would i make it so the bias can work the other way Bias high ?

6. ### Rappelr

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;
}