尝试计算框的分数时的十进制精度损失

我有一个场景,我有一个包含3jar的标准盒子。 出于显示和查询的目的,我必须根据其标准配置的十进制数量进行报告。 不可能说1盒3jar,1盒2jar……等等

例如,最初我将有1盒3jar
然后我删除1可以产生0.66重复的3jarjar
然后我再删除1 个jar子,产生0.33个重复的3个jar子
然后我删除最终可以导致0.0000000000000000000000000001盒3jar

当我删除最终的jar头时,我希望该值为0盒3jar,因为现在每个jar子都已从原始盒子中移除。 我很欣赏由于在处理有限数量的位时无法表示0.33重复这一事实而导致精度损失。

问题:对于那些需要使用舍入(可能是财务)的系统有更多经验的人,我有哪些选择来处理这个问题? 如何删除最后一个可能意味着该框不再存在?

编辑:
到底。 我使用了Loren Pechtel的建议并存储了jar头的数量,然后当我需要显示多少标准盒子时我将jar头总数除以标准盒子中的jar头数量仍然给出递归结果但这对报告来说很好事情的一面。

以下是一些代码,我希望这些代码可以帮助更多地概述问题: –

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 allBoxes = new List(); 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; } } 

我解决这些问题的方法是不要这样做。

当它是财务资料时尤其如此。

财务方面通常很容易处理 – 用便士做所有的工作,而不是美元。

我对你的问题的第一反应是储存jar而不是jar子。

为什么不使用int作为您的数量? 似乎你不想允许移除1.078261563(例如)jar头 – 是吗?

在阅读了一下之后,我想我看到了这里的困境。 看起来你正在将尺寸(盒子的最大容量),数量(盒子中当前包含的内容)组合成仅百分比(数量与大小的比率)。 如果你稍微重新设计,跟踪尺寸和数量并计算完全百分比,我认为它会清除:

 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,则在显示合理的时候设置精度,比如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);