Proportional Percentage Scaling

$\begingroup$

I've been breaking my head in trying to calculate the proportional scaling of percentages, in which the end result should always quantify to 100%.

For example:

Person A - 60%
Person B - 40%

When adding person C with 50%, the following scaling occurs, in proportion to their original percentage of what's left:

Person A: 30%
Person B: 20%
Person C: 50%

When amending an entry; for example, setting Person A to 10%, the following occurs:

Person A: 10%
Person B: 30%
Person C: 60%

I was able to calculate this off the top of my head (strange - that never works), however I'm uncertain as to how to apply this in mathematical formula, and in its simplest form; in such a way that the calculation works in all scenarios, whether adding, amending or removing persons and their percentages.

At every calculation, I have existing reference to the following:

  • How many items (persons) there currently are
  • The original percentage allocated to that person

Your help would be greatly appreciated.

Edit

I'm not sure how to explain it in a better form, but I hope the following tables may explain a bit better:

Where ? are the values to be calculated

The closest I've come so far:

var beneficiaries = [ 100
]; // Current state of beneficiaries
const calculateBeneficiaryRatio = (action, value = 0, index = 0) => { let results = []; let cur_percentage, new_percentage; switch(action) { case "add": for(let i in beneficiaries) { cur_percentage = beneficiaries[i]; new_percentage = (100 - value) * (cur_percentage / 100); beneficiaries[i] = new_percentage; } beneficiaries.push(value); return beneficiaries; break; case "remove": value = beneficiaries[index]; beneficiaries.splice(index, 1); for(let i in beneficiaries) { cur_percentage = beneficiaries[i]; new_percentage = cur_percentage + (value / beneficiaries.length); beneficiaries[i] = new_percentage; } return beneficiaries; break; case "update": beneficiaries[index]; for(let i in beneficiaries) { cur_percentage = beneficiaries[i]; new_percentage = (100 - value) * (cur_percentage / 100) + (value / beneficiaries.length); beneficiaries[i] = new_percentage; } return beneficiaries; break; }
}
beneficiaries = calculateBeneficiaryRatio('add', 29);
console.log(beneficiaries);
beneficiaries = calculateBeneficiaryRatio('add', 20);
console.log(beneficiaries);
beneficiaries = calculateBeneficiaryRatio('remove', null, 1);
console.log(beneficiaries);
beneficiaries = calculateBeneficiaryRatio('update', 20, 0);
console.log(beneficiaries);
$\endgroup$ 4

1 Answer

$\begingroup$

Neither of your two examples matches your description: instead of $(85,5,10)$, I would have expected $(81,9,10)$, because that preserves the ratio $a:b$, i.e., $90:10=81:9$. Maybe there was a miscalculation?

If that's the case, then here's the idea: suppose you have some percentages $(a,b,c,d)$ and you're changing $d$ to $d+\Delta$. Then we need to remove a total of $\Delta$ from the other three while preserving the ratio $a:b:c$.

Looking at $a$ as a fraction of $a+b+c$, we have $\frac a{a+b+c}$. This is the fraction of $\Delta$ by which $a$ must decrease, so the new value of $a$ will be$$a - \left(\frac a{a+b+c}\right)\Delta,$$which after factoring out the $a$ we can rewrite as$$a\left(1 - \frac \Delta{a+b+c}\right).$$

To put it more simply, let $T$ be the total of the first three values: $T=a+b+c$. Then the new value of $a$ will be $a\left(\frac{T-\Delta}T\right).$

The changes to $b$ and $c$ are similar; therefore, the new values of $(a,b,c,d)$ will be$$\left(a\left(\frac{T-\Delta}T\right), b\left(\frac{T-\Delta}T\right), c\left(\frac{T-\Delta}T\right), d + \Delta\right).$$

Finally, note that the case $a=b=c=0$ will have to be given special treatment.

$\endgroup$ 9

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like