正确的总和与总和,抵消舍入误差

Per*_*röm 8 php rounding-error divide

用PHP编写的带有MySQL数据库的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.

有些人可能会争辩说,只要有足够的小数,这只是在拥有大量行时的问题.但在一个经济的系统中,我认为从一开始就拥有一个故障安全系统是很重要的.它需要是可扩展的,甚至不会有任何误差.不公平是好的,只是没有错误.

类似的问题:总和分值问题(处理舍入误差)

y2o*_*2ok 1

这似乎有效 - http://jsfiddle.net/nQakD/

\n\n

使用 jQuery 作为示例,但如果您了解 PHP,您应该能够轻松地将其转换为 PHP。如果您还需要 php 代码,请告诉我,我会为您编写。

\n\n

我也会将代码粘贴到这里 -

\n\n
$(document).ready(function() {\n    var price = 17.48, people = 4, payment = (price/people).toFixed(2), count=0;\n    var payments = [];\n    for(i = 0; i < people; i++) {\n       payments.push(payment);   \n    }\n\n    if(payment*people != price) {\n        var currentPayment = payment*people;\n\n        $(payments).each(function() {\n            if(currentPayment < price) {\n                currentPayment = (currentPayment-this).toFixed(2);\n                var newPayment = parseFloat(this)+0.01;\n                payments[count] = newPayment.toFixed(2);\n                currentPayment = parseFloat(currentPayment)+parseFloat(newPayment);\n            }\n            else if(currentPayment > price) {\n                currentPayment = (currentPayment-this).toFixed(2);\n                var newPayment = parseFloat(this)-0.01;\n                payments[count] = newPayment.toFixed(2);\n                currentPayment = parseFloat(currentPayment)+parseFloat(newPayment);\n            }\n            count++;\n        });   \n\n    }  \n    $(payments).each(function() {\n        $("#result").append("<b>"+this+"</b><br/>");\n    });       \n});\xe2\x80\x8b\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑:

\n\n

这是有效的 php 代码 -

\n\n
$price = 13.34;\n$people = 4;\n$payment = (float)$price/$people;\n$payment = 0.01 * (int)($payment*100);\n$count = 0;\n$payments = Array();\nfor($i = 0; $i < $people; $i++) {\n    array_push($payments, $payment);\n}\nif($payment*$people != $price) {\n    $currentPayment = $payment*$people;\n    foreach($payments as $pay) {\n        if($currentPayment < $price) {\n            $currentPayment = $currentPayment-$pay;\n            $currentPayment = 0.01 * (int)($currentPayment*100);               \n            $newPayment = (float)$pay+0.01;\n            $newPayment = 0.01 * (int)($newPayment*100);\n            $payments[$count] = $newPayment;\n            $currentPayment = (float)$currentPayment+$newPayment;\n        }\n        else if($currentPayment > $price) {\n            $currentPayment = $currentPayment-$pay;\n            $currentPayment = 0.01 * (int)($currentPayment*100);               \n            $newPayment = (float)$pay-0.01;\n            $newPayment = 0.01 * (int)($newPayment*100);\n            $payments[$count] = $newPayment;\n            $currentPayment = (float)$currentPayment+$newPayment;\n        }\n        $count++;\n    }\n}\nforeach($payments as $payed) {\n    echo \'<b>\'.$payed.\'</b><br />\';\n}\xe2\x80\x8b\xe2\x80\x8b\xe2\x80\x8b\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑2:

\n\n

这应该可以解决 js 问题 - http://jsfiddle.net/nQakD/也更新了上面的代码。

\n\n

编辑3:

\n\n

编辑了 PHP 代码和 JS 代码,使其适用于所有示例 - http://jsfiddle.net/nQakD/

\n