9

MySQL データベースを使用して PHP でコーディングされた Web アプリ。

私は、費用を分割するときに、多くの人々のさまざまな費用を計算するシステムを持っています。たとえば、人物 Aが 10 で何かを購入し、人物 B、C、および Dが費用を分割する必要があります。

したがって、システムは、人物 Aについては 10 の肯定レコードを登録し、 B、C、および Dについては 10/3 の否定レコードを登録する必要があります。

ただし、これが行われると。B、C、および Dはすべて、丸め後に -3.33 になります。もちろん、どれを合計しても 10 にはなりません。この問題を解決する最善の方法は何ですか? 最適な解決策は、わずかに大きなコストを受け取る人をランダム化することです。

考えられる解決策の 1 つは、最後の人の負債を にすることですが、たとえば 13.34 の費用を4 人10 - (A + B)で分割すると問題が発生します。異なる部分は 3.34、3.34、3.34、および 3.32 になり、最適な分割は 3.34、3.34、3.33、3.33 になります。

十分な数の小数を使用すると、これは大量の行がある場合にのみ問題になると主張する人もいるかもしれません。しかし、経済的なシステムでは、最初からフェイルセーフシステムを備えていることが重要だと思います。スケーラブルである必要があり、わずかなエラーであっても許されません。不公平は問題ありませんが、エラーではありません。

類似問題:分割値の合計問題 (丸め誤差の処理)

4

2 に答える 2

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/

于 2012-07-23T12:24:35.390 に答える
0

おそらく、すべてのユーザーに対して新しい「丸め残高」を作成します。3 分割するのが 10 の場合、各ユーザーは 3.34 を支払うことになります。また、各ユーザーは、丸め残高に対して 2/3 セントを持ちます。(これは、私が推測するテキストとして保存する必要があります)。

次回同じことが起こったときは、丸め残高を確認してください.彼らは 2/3 セントを持っているので、今は 3 分の 1 を引くことができます (したがって、彼らは丸め残高に 1/3 セントを持っています)、3.33 だけを請求します。 .

于 2012-07-23T12:08:05.527 に答える