2012-03-02 53 views
3

我有一個場景,我有一個包含3個罐子的標準盒子。出於顯示和查詢的目的,我必須按照其標準配置的十進制數進行報告。 這是不可能說的3罐1組中,2罐1箇中...等
當試圖計算一個盒子的分數時十進制精度損失

例如,最初我將有3罐1盒
我然後除去1個可以得到在0.66重複的3罐
框我然後除去1更能夠導致0.33重複的3罐
框然後我移除最終罐導致框的3 0.0000000000000000000000000001

當我刪除最後的罐頭時,我想要的值是0盒3罐,因爲現在每個罐頭都已經從原盒中取出。我意識到,由於在處理有限數量的比特時不能表示0.33,所以存在精度損失。

問題:對於那些在需要使用四捨五入的系統中有更多經驗的人(可能有財務),我有什麼方法可以解決這個問題?如何去除最後一個可能意味着該框不再存在?

編輯:
最後。我使用了Loren Pechtel的建議,然後存儲罐的數量,然後當我需要顯示多少個標準框時,我將罐的總數除以標準框中的罐數,仍然給出遞歸結果,但這對於報告事物的一面。

下面是一些代碼,我希望將在概述問題多一些幫助: -

 static void Main(string[] args) 
    { 
     var box = new StandardBox(3); 
     var boxDetail = new BoxDetail(1.0m, box); 

     var allBoxes = new AllBoxes(); 
     allBoxes.AddBox(boxDetail); 
     allBoxes.RemoveItemFromBox(boxDetail, 1.0m); 
     Console.WriteLine(allBoxes); 
     allBoxes.RemoveItemFromBox(boxDetail, 1.0m); 
     Console.WriteLine(allBoxes); 
     allBoxes.RemoveItemFromBox(boxDetail, 1.0m); 
     Console.WriteLine(allBoxes); 
     Console.ReadLine(); 
    } 
} 

public class StandardBox 
{ 
    private decimal _quantity; 
    public StandardBox(decimal quantity){_quantity = quantity;} 
    public decimal Quantity {get { return _quantity; }} 
} 

public class BoxDetail 
{ 
    private decimal _quantity; 
    private StandardBox _box; 

    public BoxDetail(decimal quantity, StandardBox box) 
    { 
     _quantity = quantity; 
     _box = box; 
    } 

    public void RemoveItem(decimal quantity) 
    { 
     var newQuantity = quantity/_box.Quantity; 
     _quantity = _quantity - newQuantity; 
    } 

    public override string ToString() 
    { 
     return _quantity.ToString() + " of " + _box.Quantity.ToString(); 
    } 
} 

public class AllBoxes 
{ 
    private List<BoxDetail> allBoxes = new List<BoxDetail>(); 

    public AllBoxes(){} 

    public void AddBox(BoxDetail box){allBoxes.Add(box);} 

    public void RemoveItemFromBox(BoxDetail box, decimal quantity) 
    { 
     var boxDetailLineToModify = allBoxes.Find(b => b.Equals(box)); 
     boxDetailLineToModify.RemoveItem(quantity); 
    } 

    public override string ToString() 
    { 
     var results = string.Empty; 
     foreach (var box in allBoxes) 
     { 
      results += box.ToString() + "\n"; 
     } 
     return results; 
    } 
} 
+0

您可以使用infiteite-precision算術庫。 – SLaks 2012-03-02 22:54:51

+0

使用雙精度而不是十進制。 – jacknad 2012-03-02 22:58:37

+0

我最初嘗試了兩次,並刪除第三罐的結果是1.11022302462516E-16 of 3 – lostinwpf 2012-03-02 23:05:17

回答

7

我的方法這樣的問題,是不這樣做。

當財務狀況尤其如此。

財務資料通常很容易處理 - 以便士而不是美元完成所有工作。

我對你的問題的第一反應是存儲罐子而不是罐子。

+0

我必須考慮到在某些情況下,盒子中罐的數量可能會有所不同。我不確定儲存罐頭的數量是否能夠解決這個問題 - 儘管我開始認爲從長遠來看,儲存罐頭可能會更好。 – lostinwpf 2012-03-02 23:07:35

1

如果你只是想顯示 0,然後設置,當你顯示的東西合理的精度,說2位小數:

public override string ToString() 
{ 
    return _quantity.ToString("D2") + " of " + _box.Quantity.ToString(); 
} 

如果你想比較的值設置爲0(或任何其他值),比較對一些小的值之差:

public bool AreEqual(double value1, double value2) 
{ 
    double EPSILON = 0.000001; 
    return Math.Abs(value1 - value2) < EPSILON; 
} 

bool IsZero = AreEqual(_quantity,0); 
2

爲什麼不使用int爲您量?無論如何,你似乎並不希望允許刪除1.078261563(例如)罐子 - 是嗎?

閱讀了一會之後,我想我在這裏看到了困境。您似乎將大小(框的最大容量),數量(框中當前包含的內容)合併爲「完全百分比」(數量與大小的比率)。如果你稍微重新設計,跟蹤大小和數量,並計算百分比全面,我認爲它會澄清一些事情:

class Box { 
    public decimal Size { get; private set; } 
    public decimal Quantity { get; private set; } 
    public decimal PercentFull { get { return this.Quantity/this.Size; } } 
    public Box(decimal size) { 
     this.Size = size; 
    } 
    public void Remove(decimal quantity) 
    { 
     this.Quantity -= quantity; 
    } 
    public void Add(decimal quantity) 
    { 
     this.Quantity += quantity; 
    } 
    public override string ToString() { 
     return this.PercentFull.ToString() + "% of " + this.Size.ToString(); 
      // Or, to be exact 
      // return this.Quantity.ToString() + " of " + this.Size.ToString(); 
    } 
} 

這似乎仍然是,根據您的(可能是消毒)例如,SizeQuantity會更適合於int - 但數學運算方式也一樣。

+0

我剛選擇罐子作爲一個簡單的例子。只需將罐子替換爲TUB的公文和BOX即可,我想從TUB中抽取0.75公升,在這種情況下,小數對我來說更有意義。 – lostinwpf 2012-03-02 23:15:02