在要四舍五入的集合中找到最高的数字,然后将其四舍五入 [英] Find the highest number in a set to be rounded down, and round it up instead

查看:84
本文介绍了在要四舍五入的集合中找到最高的数字,然后将其四舍五入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如标题所述,我有一组对象-称为分配-其中包含描述&一个号码.集合中的所有数字加起来等于100%,但是出于显示目的,我有时会舍入为一个整数.在某些情况下,四舍五入后我得到了99%.

As the title describes, I have a set of objects - call them Allocations - which contain a description & a number. All numbers in the set add up to 100%, but for display purpose I sometimes round to a whole percent. In some edge cases, having rounded the numbers I end up with 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!)

所请求的解决方案虽然不完美,但是可以解决,它是找到要四舍五入的最高解决方案,然后将其向上舍入.在上面的示例中,四舍五入后的1.42%将变为2%. 将要舍入的最高位"是指被舍入到最远的位.因此,将1.42%向下舍入为0.42,而65.23仅向下舍入为0.23

The requested solution, which is imperfect but will do, is to find the highest one to be rounded down, and round it up instead. In the example above, 1.42% would become 2% when rounded. By "Highest one to be rounded down" I mean the one which is being rounded the furthest. Hence 1.42% is being rounded down by 0.42 whereas the 65.23 is only being rounded down 0.23

所以现在代码,我有一个课

So now the code, I have a class

public class Allocation
{
  public string Description {get;set;}
  public doubel Percentage {get;set;}
}

这些被保存在IEnumerable<Allocation>中.因此,潜在地使用LINQ,我如何确定哪一个是要四舍五入的.更具体地说,如何生成带有四舍五入数字的新IEnumerable<Allocation>.

And these are held in an IEnumerable<Allocation>. So, potentially using LINQ, how can I determine which one is the one to round up. Or more specifically, how can I generate a new IEnumerable<Allocation> with the numbers rounded.

如果有人有其他建议总是将舍入百分比始终等于100%,那就更好了!

If anyone has any other suggestion for always making rounded percentage always equate to 100% that would be even better!

推荐答案

正如ho1所指出的,将1加到特定行的解决方案并不能解决真正的问题.

As ho1 has indicated, the solution to add 1 to a specific row doesn't solve the real problem.

请考虑以下情形:

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

这里有一些未经测试的代码,可能会使您接近需要去的地方.此处可能有符号错误,请当心.

Here's some untested code that might get you close to where you need to go. There's probably a sign error in here so watch out.

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();

注意:按引入的错误进行订购可能会导致并列.考虑3个项目的情况,只有一个项目会获得+1 ...您可能希望该项目被一致选择.如果期望从多次运行中获得一致的结果,则应打破联系.

Note: Ordering by introduced error can result in ties. Consider the 3 items case, only one item will get +1... you may expect that item to be consistently chosen. If consistent results are expected from multiple runs, ties should be broken.

这篇关于在要四舍五入的集合中找到最高的数字,然后将其四舍五入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆