Мне нужен алгоритм (желательно абстрактный или в очень понятном коде Python или PHP), который позволяет справедливо распределять выручку как в краткосрочной, так и в долгосрочной перспективе, исходя из следующих ограничений:
- Каждая входящая сумма будет целым числом.
- Каждое распределение также будет целым числом.
- Каждый человек в распределении должен получать долю дохода, выраженную в фиксированной доле. Эти дроби, конечно, могут быть помещены под общий знаменатель (представьте себе целые проценты со знаменателем 100). Сумма всех числителей равна знаменателю (100 в случае процентов).
- Чтобы сделать это справедливым в краткосрочной перспективе, человек
i
должен получать либоfloor(revenue*cut[i])
, либоceil(revenue*cut[i])
. РЕДАКТИРОВАТЬ: Позвольте мне подчеркнуть, чтоceil(revenue*cut[i])
не обязательно равно1+floor(revenue*cut[i])
, поэтому некоторые алгоритмы не работают, в том числе один из представленных (см. мой комментарий к ответу Андрея). - Чтобы сделать это справедливым в долгосрочной перспективе, по мере накопления платежей фактические полученные сокращения должны быть как можно ближе к теоретическим сокращениям, предпочтительно всегда менее 1 единицы. В частности, если общий доход кратен знаменателю общей дроби, каждый человек должен был получить соответствующее кратное его числителю.
- [Edit] Забыл добавить, что общая сумма, распределяемая каждый раз, конечно же, должна соответствовать полученной входящей сумме.
Вот пример для наглядности. Предположим, есть три человека, между которыми распределяется доход, и один должен получить 31%, другой - 21%, а третий должен получить 100–31–21 = 48%.
А теперь представьте, что есть доход в 80 монет. Первый человек должен получить монеты floor(80*31/100)
или ceil(80*31/100)
, второй человек должен получить либо floor(80*21/100)
, либо ceil(80*21/100)
, а третий человек - либо floor(80*48/100)
, либо ceil(80*48/100)
.
А теперь представьте, что появился новый доход в 120 монет. Каждый человек должен снова получить либо нижний, либо верхний предел своих соответствующих сокращений, но поскольку общий доход (200) является кратным знаменателю (100), теперь каждый человек должен иметь свои точные сокращения: у первого человека должно быть 62 монеты , у второго человека должно быть 42 монеты, а у третьего - 96 монет.
Я думаю, что у меня есть алгоритм, рассчитанный на случай распределения доходов между двумя людьми. Это выглядит так (для 35% и 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]
Я думаю, что этот простой алгоритм удовлетворяет всем моим ограничениям, но я не нашел способа распространить его на более чем двух человек, не нарушив хотя бы одного. Может ли кто-нибудь придумать расширение для нескольких человек (или, возможно, доказать его невозможность)?