编程语言
首页 > 编程语言> > python – 在算法和公平之后拆分账单,之后:)

python – 在算法和公平之后拆分账单,之后:)

作者:互联网

我正试图解决你可能遇到的以下现实问题:

你和一些朋友共进晚餐,你们都同意平均分摊账单.除了账单终于到来之外,你发现不是每个人都有足够的现金(如果有的话,便宜的混蛋).

所以,你们中的一些人比其他人付出更多…之后你们回家并试着决定“谁欠谁的金额?”.

这个,我正在努力解决算法问题.公平:)

一开始看起来这么容易,但是我已经陷入了四舍五入的困境,我觉得这完全是一个失败者;)

关于如何解决这个问题的任何想法?

编辑:一些python代码,以显示我的困惑

>>> amounts_paid = [100, 25, 30]
>>> total = sum(amounts_paid)
>>> correct_amount = total / float(len(amounts_paid))
>>> correct_amount
51.666666666666664
>>> diffs = [amnt-correct_amount for amnt in amounts_paid]
>>> diffs
[48.333333333333336, -26.666666666666664, -21.666666666666664]
>>> sum(diffs)
7.1054273576010019e-015

理论上,差异的总和应为零,对吧?

另一个例子它工作:)

>>> amounts_paid = [100, 50, 150]
>>> total = sum(amounts_paid)
>>> correct_amount = total / float(len(amounts_paid))
>>> correct_amount
100.0
>>> diffs = [amnt-correct_amount for amnt in amounts_paid]
>>> diffs
[0.0, -50.0, 50.0]
>>> sum(diffs)
0.0

解决方法:

诀窍是将每个人视为一个单独的帐户.

您可以轻松确定(从原始账单中)每个人应支付多少钱.将此设置为每个人的负数.接下来,通过将支付的金额添加到其帐户中来记录每个人已支付的金额.在这一点上,多付(贷款人)的人将有正余额,而少付(借款人)的人将有负余额.

除非在只有一个贷方的明显情况下,借款人欠每个贷方的钱没有一个正确的答案.借款人支付的金额可以转给任何贷方.只需将金额加到借款人的总金额中,然后从收到付款的贷方中扣除金额.

当所有账户都达到零时,每个人都已经付清了.

编辑(回复评论):

I think my problem lies with the fact that the amount is not always evenly divisible, so coming up with an algorithm that handles this elegantly seems to trip me up again & again.

在处理美元和美分时,没有100%干净的方法来处理舍入.有些人会比其他人多支付1美分.公平的唯一方法是随机分配额外的0.01美元(根据需要).当通过分割账单计算“欠款”时,这只会进行一次.它有时有助于将货币价值存储为美分,而不是美元(例如,1234美元将存储为1234美元).这允许您使用整数而不是浮点数.

为了分配额外的美分,我会做以下事情:

total_cents = 100 * total;
base_amount = Floor(total_cents / num_people);
cents_short = total_cents - base_amount * num_people;
while (cents_short > 0)
{
    // add one cent to a random person
    cents_short--;
}

注意:“随机”分配便士的最简单方法是将第一个额外分配给第一个人,第二个分配给第二个,等等.如果您总是以相同的顺序输入相同的人,这只会成为一个问题.

标签:python,algorithm,math,floating-accuracy
来源: https://codeday.me/bug/20190712/1442743.html