2012-07-23 53 views
8

以PHP編碼的Web應用程序和MySQL數據庫。糾正總計除數和舍入誤差

我有一個系統可以在拆分成本時計算許多人的不同成本。例如Person A買東西10和人B,C和D應該分攤成本。

系統應爲此寄存器正記錄人的10甲和10/3負記錄B,C和D.

然而,當這樣做時; 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

「不公平是正常的,只是沒有錯誤。」 - 愛它 – user1020317 2012-07-23 12:01:33

+0

+1演示文稿 – Smandoli 2012-07-23 12:10:22

+0

我想我會找到兩個最接近的分隔值,然後在他們被分配時在兩者之間切換。然後找出如何處理(潛在)最後一個奇數值。 – Smandoli 2012-07-23 12:11:24

回答

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:

這個sh請修正上面的js問題 - http://jsfiddle.net/nQakD/更新的代碼。

編輯3:

編輯PHP代碼和JS代碼,以便它的工作,所有的例子 - http://jsfiddle.net/nQakD/

+0

非常感謝!儘管有幾個問題: ** 1。**在將$ payment付款爲int時,是否導致3.33或3.34,即。是否圓整? ** 2。**在奇妙的js腳本中嘗試不同的值時,我可以得到未舍入到小數點後兩位的值。我應該在if語句中的某個地方做類似的int-cast嗎? – 2012-07-23 14:28:27

+0

1)它會導致3.33。 2)你能舉幾個例子嗎? – y2ok 2012-07-23 14:31:10

+0

查看新的答案。 – y2ok 2012-07-23 14:37:05

0

也許做一個新的 「四捨五入的平衡」 上爲每一位用戶。如果是10分三種方式,那麼每個用戶將支付3.34。每個用戶也會有三分之一的分數到他們的舍入餘額。 (這將不得不按照我所設想的文本進行存儲)。

下次發生同樣的事情時,請檢查舍入餘額..他們有2/3的分,所以現在你可以拿掉三分之一(所以他們現在有三分之一的舍入餘額)並只收取3.33。