I am after an algorithm (preferably abstract or in very clear Python or PHP code) that allows for a fair distribution of revenue both in the short and in the long term, based on the following constraints:
- Each incoming amount will be an integer.
- Each distribution will be also an integer amount.
- Each person in the distribution is set to receive a cut of the revenue expressed as a fixed fraction. These fractions can of course be put under a common denominator (think integer percentages with a denominator of 100). The sum of all numerators equals the denominator (100 in the case of percentages)
- To make it fair in the short term, person
imust be receiving eitherfloor(revenue*cut[i])orceil(revenue*cut[i]). EDIT: Let me emphasize thatceil(revenue*cut[i])is not necessarily equal to1+floor(revenue*cut[i]), which is where some algorithms fail including one presented (see my comment on the answer by Andrey). - To make it fair in the long term, as payments accumulate, the actual cuts received must be as close to the theoretical cuts as possible, preferably always under 1 unit. In particular, if the total revenue is a multiple of the denominator of the common fraction, every person should have received the corresponding multiple of their numerator.
- [Edit] Forgot to add that the total amount distributed every time must of course add up to the incoming amount received.
Here's an example for clarity. Say there are three people among which to distribute revenue, and one has to get 31%, another has to get 21%, and the third has to get 100-31-21=48%.
Now imagine that there's an income of 80 coins. The first person should receive either floor(80*31/100) or ceil(80*31/100) coins, the second person should receive either floor(80*21/100) or ceil(80*21/100) and the third person, either floor(80*48/100) or ceil(80*48/100).
And now imagine that there's a new income of 120 coins. Each person should again receive either the floor or the ceiling of their corresponding cuts, but since the total revenue (200) is a multiple of the denominator (100), each person should have now their exact cuts: the first person should have 62 coins, the second person should have 42 coins, and the third person should have 96 coins.
I think I have an algorithm figured out for the case of two people to distribute the revenue among. It goes like this (for 35% and 65%):
set TotalRevenue to 0
set TotalPaid[0] to 0
{ TotalPaid[1] is implied and not necessary for the algorithm }
set Cut[0] to 35
{ Cut[1] is implied and not necessary for the algorithm }
set Denominator to 100
each time a payment is received:
let Revenue be the amount received this time
set TotalRevenue = TotalRevenue + Revenue
set tmp = floor(TotalRevenue*Cut[0]/Denominator)
pay person 0 the amount of tmp - TotalPaid[0]
set TotalPaid[0] = tmp
pay person 1 the amount of TotalRevenue - TotalPaid[0]
I think that this simple algorithm meets all of my constraints, but I have not found the way to extend it to more than two people without violating at least one. Can anyone figure out an extension to multiple people (or perhaps prove its impossibility)?