Jam*_*iec 5 linq ienumerable rounding c#-3.0
正如标题所描述的那样,我有一组对象 - 称为Allocations - 包含描述和数字.集合中的所有数字加起来都是100%,但出于显示目的,我有时会达到整数百分比.在某些边缘情况下,对数字进行舍入后,最终得出99%.
例:
Description | Actual | Rounded
===============================
Allocation A | 65.23% | 65%
Allocation B | 25.40% | 25%
Allocation C | 7.95% | 8%
Allocation D | 1.42% | 1%
===============================
Total | 100% | 99% (Bad!)
Run Code Online (Sandbox Code Playgroud)
所要求的解决方案虽然不完善但会做到,但要找到最高的解决方案,然后将其四舍五入.在上面的示例中,四舍五入时1.42%将变为2%.编辑:通过"最高的一个向下舍入"我的意思是最圆的一个.因此1.42%下调0.42而65.23仅下跌0.23
所以现在代码,我有一个类
public class Allocation
{
public string Description {get;set;}
public doubel Percentage {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
这些都是在一个IEnumerable<Allocation>.因此,可能使用LINQ,我如何确定哪一个是圆形的.或者更具体地说,如何生成IEnumerable<Allocation>带有舍入数字的新数据.
如果有人有任何其他建议,总是将圆整百分比总是等于100%甚至会更好!
正如 ho1 所指出的,将 1 添加到特定行的解决方案并不能解决真正的问题。
考虑以下场景:
3 items evenly divided, 100/3 = 33 ; 33 * 3 = 99 ; Error = -1
7 items evenly divided, 100/7 = 14 ; 14 * 7 = 98 ; Error = -2
66 items evenly divided, 100/66 = 2 ; 2 * 66 = 132 ; Error = 32
Run Code Online (Sandbox Code Playgroud)
这里有一些未经测试的代码,可能会让您接近您需要去的地方。这里可能有一个符号错误,所以要小心。
public class AllocationRoundingWrapper
{
public Allocation Original {get;set;}
public double Rounded {get;set;}
public double IntroducedError()
{
return Rounded - Original.Percentage;
}
}
//project the Allocations into Wrappers for rounding efforts.
List<Allocation> source = GetAllocations();
List<AllocationRoundingWrapper> roundingWrappers = source
.Select(a => new AllocationRoundingWrapper()
{
Original = a,
Rounded = Math.Round(a.Percentage)
}).ToList();
int error = (int) roundingWrappers.Sum(x => x.IntroducedError());
//distribute the rounding errors across the
// items with the absolute largest error.
List<RoundingWrapper> orderedItems = error > 0 ?
roundingWrappers.OrderByDescending(x => x.IntroducedError()).ToList() :
roundingWrappers.OrderBy(x => x.IntroducedError()).ToList();
IEnumerator<RoundingWrapper> enumerator = orderedItems.GetEnumerator();
while(error > 0)
{
enumerator.MoveNext();
enumerator.Current.Rounded += 1.0;
error -= 1;
}
while(error < 0)
{
enumerator.MoveNext();
enumerator.Current.Rounded -= 1.0;
error += 1;
}
//project back into Allocations for the result
List<Allocation> result = roundingWrappers
.Select(x => new Allocation()
{
Description = x.Original.Description,
Percentage = x.Rounded
}).ToList();
Run Code Online (Sandbox Code Playgroud)
注意:按引入的错误排序可能会导致平局。考虑 3 项的情况,只有一项会获得 +1...您可能期望该项会被一致选择。如果多次运行的结果一致,则应打破平局。
| 归档时间: |
|
| 查看次数: |
813 次 |
| 最近记录: |