2012-07-23 16 views
8

MySQLデータベースを使用してPHPでコーディングされたWebアプリケーション。分数の合計と正数の丸め誤差を相殺

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

システムは、これが行われる場合、しかしながらB、CおよびD

ため10/3の 10及び負レコードの正レコードを登録し、そのためべきです。 B、CおよびDは、すべて丸めた後に-3.33を有する。どちらのコースはで、が合計で10になりません。この問題についてはどのような方法がありますか?最適解は人が何を得るのかをランダム化する。私はちょうど最後の人の債務は10 - (A + B)なりましょう、しかし4人は、例えば、13.34のための費用を分割するならば、問題がある場合

一つの可能​​なソリューションです。異なる部分は3.34,3.34,3.34,3.32となり、最適な分割は3.34,3.33,3.33,3.33となります。

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

同様の問題:sum divided values problem (dealing with rounding error)

+0

「不公平は問題ありません。エラーではありません。 - それを愛する – user1020317

+0

+1プレゼンテーション – Smandoli

+0

私は2つの最も近い分割値を見つけて、2つの値が割り当てられている間に切り替えると思います。次に、最後の奇数値(潜在的な)で何をすべきかを把握します。 – Smandoli

答えて

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 />'; 
}​​​ 

EDIT 2:

このsh ouldはjsの問題を修正しました - http://jsfiddle.net/nQakD/上記のコードも更新されました。

EDIT 3:

編集PHPコードとJSコードは、すべての例では動作しないので - http://jsfiddle.net/nQakD/

+0

ありがとうございます!しかし、いくつかの質問: ** 1。** $支払をintとしてキャストすると、結果は3.33または3.34となります。丸いかどうか? ** 2。**素晴らしいjsスクリプトでさまざまな値を試してみると、2小数点以下に丸められない値を得ることができます。 if文のどこかで同様のint-castを行うべきですか? –

+0

1)3.33になります。 2)私にいくつかの例を教えてもらえますか? – y2ok

+0

新しい回答を確認してください。 – y2ok

0

たぶん、すべてのユーザーのための最高の新しい "丸めバランス" を作ります。 3つの方法で分割する場合は10、それぞれのユーザーは3.34を支払うことになります。各ユーザーはまた、丸めのバランスの2/3のパーセントを持っています。 (これは私が推測するテキストとして保存する必要があります)。

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