如何在计入交易手续费后平均拆分付款
结论
如果手续费由第 1 方在转账金额之外支付,并从这笔 $1000 中一并扣除,那么每位接收方理论上应收到:
[ \boxed{$196.92671395} ]
每笔交易的理论手续费约为:
[ 196.92671395 \times 1.9% + 0.1 = $3.84160757 ]
完成 4 笔交易后,第 1 方也会剩下 $196.92671395,最终 5 方余额相等。
实际支付通常只能精确到分,因此很难做到完全相等。假设手续费同样按分四舍五入,可以向三方各转 $196.93,向另一方转 $196.92。第 1 方最终剩余 $196.93,各方余额的最大差额为 $0.01。
计算公式
设:
- 总金额为 (T)
- 参与方数量为 (N)
- 百分比手续费率为 (r)
- 每笔固定手续费为 (f)
- 第 1 方需要发起 (N-1) 笔交易
- 每位接收方获得 (x)
手续费由发送方额外承担时,每笔交易会从第 1 方的余额中扣除:
[ x + rx + f ]
完成所有交易后,第 1 方的余额为:
[ T-(N-1)(x+rx+f) ]
要让这个余额与其他人的余额 (x) 相等,需要满足:
[ T-(N-1)(x+rx+f)=x ]
整理可得:
[ \boxed{ x=\frac{T-(N-1)f}{N+(N-1)r} } ]
代入题目数据:
[ T=1000,\quad N=5,\quad r=0.019,\quad f=0.1 ]
因此:
[ x= \frac{1000-4\times0.1} {5+4\times0.019}
\frac{999.6}{5.076} \approx196.92671395 ]
再验证第 1 方的余额:
[ 1000-4\times(196.92671395+196.92671395\times0.019+0.1) \approx196.92671395 ]
Python 示例
货币计算不适合直接使用二进制浮点数 float,因为它可能产生难以控制的精度误差。这里可以使用 Decimal:
from decimal import Decimal, getcontext
getcontext().prec = 28
def calculate_equal_payment(total, parties, rate, fixed_fee):
total = Decimal(str(total))
rate = Decimal(str(rate))
fixed_fee = Decimal(str(fixed_fee))
transactions = parties - 1
payment = (
total - Decimal(transactions) * fixed_fee
) / (
Decimal(parties) + Decimal(transactions) * rate
)
fee_per_transaction = payment * rate + fixed_fee
sender_balance = total - Decimal(transactions) * (
payment + fee_per_transaction
)
return {
"payment": payment,
"fee_per_transaction": fee_per_transaction,
"sender_balance": sender_balance,
}
result = calculate_equal_payment(
total="1000",
parties=5,
rate="0.019",
fixed_fee="0.1",
)
print("每位接收方获得:", result["payment"])
print("每笔手续费:", result["fee_per_transaction"])
print("第 1 方最终余额:", result["sender_balance"])
理论计算结果约为:
每位接收方获得:196.9267139479905437352245863
每笔手续费:3.841607565011820330969267140
第 1 方最终余额:196.9267139479905437352245863
处理货币取整
支付系统通常会将转账金额和手续费限制为两位小数。假设手续费按 ROUND_HALF_UP 四舍五入:
- 转账
$196.93时,手续费为$3.84 - 转账
$196.92时,手续费也为$3.84
可以采用下面的拆分方式:
| 参与方 | 最终余额 |
|---|---|
| 第 1 方 | $196.93 |
| 第 2 方 | $196.93 |
| 第 3 方 | $196.93 |
| 第 4 方 | $196.93 |
| 第 5 方 | $196.92 |
总扣款为:
[ 3\times(196.93+3.84)+(196.92+3.84)=803.07 ]
第 1 方剩余:
[ 1000-803.07=196.93 ]
最后一分钱无法平均分给 5 方。可以将它固定分给某一方、随机分配,或者在多次结算中轮换分配。
如果手续费从到账金额中扣除
有些支付平台不会向发送方额外收取手续费,而是直接从转账金额中扣除。假设第 1 方每次提交的转账金额为 (g),接收方实际到账:
[ (1-r)g-f ]
完成 (N-1) 笔交易后,第 1 方剩余:
[ T-(N-1)g ]
让第 1 方的余额与接收方的实际到账金额相等:
[ T-(N-1)g=(1-r)g-f ]
可以得到:
[ \boxed{ g=\frac{T+f}{N-r} } ]
代入数据:
[ g=\frac{1000.1}{4.981} \approx200.78297531 ]
接收方实际到账约为:
[ 200.78297531\times0.981-0.1 \approx196.86809878 ]
编写代码前,需要先确认支付平台如何收取手续费:是从发送方余额中额外扣除,还是从接收方的到账金额中扣除。同时还要确认手续费在哪个阶段取整,以及不足一分时如何处理。这些规则都会改变计算公式和最终结果。
备注:内容仅供参考。
