I’m running into a math problem I don’t know how to wrap my head around. I have 4 different result A, B, C, D. In order to randomly select a result I can do random number 1-100 and do a IF <25 result A… By this method I can ensure a 25% chance for each result. The question is how can I modify this dynamically, say I want to give C a +10% chance of occurring.
Any help or input is welcome.
Well, that depends on if that percentage should be an actual absolute percentage. Usually precentages are expressed with values in the range of 0 to 1. So a 10% chance would be “0.1” if “1.0” is 100%
If you want an absolute percentage increase you have to ensure that all individual percentages add up to exactly “1.0”. That means if you want a 10% increase you would have to decrease the others. If you just want a relative distribution like 25:25:25:35
You can simply add up all weight values and either get a random number between 0 and that sum or “normalize” each weight by that sum.
So in this example the sum is 25 + 25 + 25 + 35 == 110
normalized the values would be roughly 0.227 : 0.227 : 0.227 : 0.318
As you can see the last element which we “increased” by “10” doesn’t get 35% but about 31.8%. In most cases when you deal with multiple items you don’t have absolute persentages (as they all have to add up to 100%) but instead a relative weight. So an item with a weight of “100” is about 100 times more likely than an item with weight 1. The idea is still the same. You add up all your weights and roll a number that is between 0 and the sum of all weights. Note that this approach will of course “always” pick one of the items as you distribute the items along the whole range.
So in case of a pure weighting system you would do
Item[] items;
float sum = 0;
for (int i =0; i < items.Length; i++)
sum = items*.weight;*
float rnd = Random.Range(0,sum);
for(int i = 0; i < items.Length; i++)
{
if (rnd < items*.weight)*
{
// we found our item
return i;
}
else
{
// subtract the current weight from the choosen number
rnd -= items*.weight;*
}
}
In case you have actual percentages you would simply do this:
// note that “percentage” here is in the range of 0 to 1
Item[] items;
float rnd = Random.Range(0f, 1f);
for(int i = 0; i < items.Length; i++)
{
if (rnd < items*.percentage)*
{
// we found our item
return i;
}
else
{
// subtract the current percentage from the choosen number
rnd -= items*.percentage;*
}
}
Of course if the percentages don’t add up to “1” it’s possible to not select any item. For example:
0.01f, 0.1f, 0.1f, 0.5f
Those add up to 0.71f. So about 30% of the time none item will be selected. Likewise when they add up to a larger value than “1” the last elements can never be choosen.
0.3f, 0.3f, 0.3f, 0.5f, 0.5f
Those add up to “1.9”. The 4th element actually has only a chance of 10% as it’s remaining 40% are outside the range. The last element can never be choosen.