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