根据定义的比例分配值

时间:2017-03-31 07:06:15

标签: python c algorithm math

我这里有一个场景。让我用一个小例子来解释。

我有10支钢笔,我必须把它交给3个人。那些人的比例如6:6:1表示如果我给人C一笔,我必须给A人和B人6-6笔。

我试图通过使用我在下面描述的简单计算来解决它。

PerPersonPen = (TotalCountofPens * PerPersonRatio)/(SumofAllPersonsRatio) 

Person A =(Int) (10*6)/13 = 4
Person B = (Int) (10*6)/13 = 4
Person C = (Int) (10*1)/13 = 0

在这里,人物C将获得0笔,但它不应该发生。我希望那个人A& B正在获得4笔,这是正确的。但是人C也应该得到1支笔。

这种情况发生在任何人与其他人相比有1个比率计数的情况下。

有人可以帮我解决这个问题吗?或者我怎样才能实现它?

4 个答案:

答案 0 :(得分:4)

一种简单的方法是保持每个人应该获得多少笔的数量。然后,只要它们是钢笔分发,你给一个应该得到最多笔的人。

以下是您的示例:

  

60/13 ,60 / 13,10 / 13 - > 1 ,0,0

     

47/13, 60/13 ,10/13 - > 1, 1 ,0

     

47/13 ,47 / 13,10 / 13 - > 2 ,1,0

     

34/13, 47/13 ,10/13 - > 2, 2 ,0

     

34/13 ,34 / 13,10 / 13 - > 3 ,2,0

     

21/13, 34/13 ,10/13 - > 3, 3 ,0

     

21/13 ,21 / 13,10 / 13 - > 4 ,3,0

     

8/13, 21/13 ,10/13 - > 4, 4 ,0

     

8 / 13,8 / 13, 10/13 - > 4,4, 1

     

8/13 ,8/13,-3 / 13 - > 5 ,4,1

<强>更新 如果你想确保每个人在可能的情况下至少收到一支笔,那么首先给每个人一支笔,优先考虑那些需要最多笔的人,以防你没有足够的笔给每个人。然后按上述步骤进行。

答案 1 :(得分:1)

Laurent G在评论部分How to round numbers fairly

中提供了一个非常有用的数学堆栈交换链接

这篇文章暗示了以下算法:

  • 为每个人计算她应该获得的x_i比率x_i = her share/sum of shares
  • C_min = numberOfPensC_max设置得足够大,以便sum_i (floor(x_i*C_max)) > numberOfPensC_max = numberOfPens + 1/(min x_i)可以正常工作)
  • C_minC_max之间进行二分搜索,直到找到C sum_i (floor(x_i*C)) = numberOfPens
  • 为止

然而,当存在关系时(例如,在两个比率值为6/13的情况下),这可能不起作用。但你可以做的是添加一个非常小的随机噪音(你加上或减去不到原始比率之间存在的最小非零差距的一半)与你的比率来打破关系并得到一般的结果,这将是“几乎公平“。

编辑:我注意到我最初选择C_max是错误的,所以我将其修改为有效的东西。不过我觉得还有改进的余地。通过在C_max中增加k,也可以找到最初的2^k numberOfPens,直到满足标准(sum_i(floor(x_i*C_max)) > numberOfPens)。

答案 2 :(得分:0)

在查看您的示例时,很明显每个人都应该至少获得您计算的结果。 只有一些人会得到更多。

我建议以下算法:

  1. 计算每个人的双倍数量。和你没有演员一样。
  2. 总结所有人的离散总和(在我们的例子中为8)。
  3. 按照尾数对人物进行排序(在点值之后)。
  4. 对于前k个人使用Math.Ceiling(assigned value),其中k是期望值 - 我们在步骤2中计算的总和。在我们的示例中为10-8。
  5. 对于其他人,请使用常规演员,如(int) (assigned value)

答案 3 :(得分:-1)

这样的东西
int_weights = [6, 6, 1]
total_weights = sum(int_weights)

to_share = 10

still_to_share = to_share
left_weight_total = total_weights

shares = []
for weight in int_weights:
    s = int(0.5 + (float(still_to_share) * weight / left_weight_total))
    still_left -= s
    left_weight_total -= weight
    shares.append(s)

这给出了相当但不绝对的公平性(这不能通过关系实现,参见我在问题评论中发布的链接)

shares

[5,4,1]

sum(shares)

0

如果你想达到公平关系,最好的结果是[4, 4, 2](或[5, 5, 0] [:auto_censored_but_not_totally:] ;-)?)你可以通过排序和考虑到达以前的分配。直到我得到一个好的论据才能成为那个挑剔的人,我会继续使用上面所示的解决方案。