使用MySQL数据库以PHP编码的Web应用程序。
我有一个系统,可以在分摊成本时计算许多人的不同成本。例如人员A 购买10件商品,人员B,C和D 应该分摊费用。
系统应该为人A 10记录正面记录,为 B,C和D记录10/3的负面记录。
然而,当这样做时;四舍五入后, B,C和D 均为-3.33。当然总计总数为10.什么是解决此问题的最佳方法?一个最优的解决方案是随机化一个人获得的成本稍高一些。
一种可能的解决方案是,如果我让最后一个人的债务为10 - (A + B)
,但如果四个人分摊成本例如13.34则会出现问题。那么不同的部分将是3.34,3.34,3.34和3.32,而最佳分割将是3.34,3.34,3.33,3.33。
有些人可能认为,使用足够的小数,这只是在拥有大量行时的问题。但在一个经济的系统中,我认为从一开始就拥有一个故障安全系统是很重要的。它需要可扩展,并且不会出现最轻微的错误。 不公平没关系,只是没有错误。
类似问题:sum divided values problem (dealing with rounding error)
答案 0 :(得分:1)
这似乎有效 - http://jsfiddle.net/nQakD/。
使用jQuery作为示例,但如果您了解PHP,则应该能够轻松地将其转换为PHP。如果你还需要php代码,请告诉我,我会为你写的。
我也会在这里粘贴代码 -
$(document).ready(function() {
var price = 17.48, people = 4, payment = (price/people).toFixed(2), count=0;
var payments = [];
for(i = 0; i < people; i++) {
payments.push(payment);
}
if(payment*people != price) {
var currentPayment = payment*people;
$(payments).each(function() {
if(currentPayment < price) {
currentPayment = (currentPayment-this).toFixed(2);
var newPayment = parseFloat(this)+0.01;
payments[count] = newPayment.toFixed(2);
currentPayment = parseFloat(currentPayment)+parseFloat(newPayment);
}
else if(currentPayment > price) {
currentPayment = (currentPayment-this).toFixed(2);
var newPayment = parseFloat(this)-0.01;
payments[count] = newPayment.toFixed(2);
currentPayment = parseFloat(currentPayment)+parseFloat(newPayment);
}
count++;
});
}
$(payments).each(function() {
$("#result").append("<b>"+this+"</b><br/>");
});
});
修改强>
这是工作的PHP代码 -
$price = 13.34;
$people = 4;
$payment = (float)$price/$people;
$payment = 0.01 * (int)($payment*100);
$count = 0;
$payments = Array();
for($i = 0; $i < $people; $i++) {
array_push($payments, $payment);
}
if($payment*$people != $price) {
$currentPayment = $payment*$people;
foreach($payments as $pay) {
if($currentPayment < $price) {
$currentPayment = $currentPayment-$pay;
$currentPayment = 0.01 * (int)($currentPayment*100);
$newPayment = (float)$pay+0.01;
$newPayment = 0.01 * (int)($newPayment*100);
$payments[$count] = $newPayment;
$currentPayment = (float)$currentPayment+$newPayment;
}
else if($currentPayment > $price) {
$currentPayment = $currentPayment-$pay;
$currentPayment = 0.01 * (int)($currentPayment*100);
$newPayment = (float)$pay-0.01;
$newPayment = 0.01 * (int)($newPayment*100);
$payments[$count] = $newPayment;
$currentPayment = (float)$currentPayment+$newPayment;
}
$count++;
}
}
foreach($payments as $payed) {
echo '<b>'.$payed.'</b><br />';
}
编辑2:
这应修复js问题 - 上面的http://jsfiddle.net/nQakD/更新代码。
编辑3:
编辑了PHP代码和JS代码,因此它适用于所有示例 - http://jsfiddle.net/nQakD/。
答案 1 :(得分:0)
也许为每个用户提供一个新的“舍入平衡”。如果以三种方式拆分为10,那么每个用户将支付3.34。每个用户的舍入余额也将为2/3分。 (这必须存储为我认为的文字。)
下次同样的事情发生时,检查四舍五入的余额......他们有2/3分,所以现在你可以减少三分之一(所以他们现在有四分之一的余额)和只收取3.33。