【问题标题】:How to divide a number into multiple parts so that the resulting sum is equal to the input?如何将一个数字分成多个部分,以使结果总和等于输入?
【发布时间】:2012-11-27 13:44:35
【问题描述】:

我试图将一个数字分成多个部分,以便部分的总和等于输入的数字。

如果我有 3.99,如果我需要分成两部分,那么预期的输出是 2 和 1.99 (2+1.99=3.99)

如果我需要将 3.99 分成 3 部分,则预期输出为 1.3、1.3 和 1.39 (1.3+1.3+1.39=3.99)

对于第一个示例,我能够输出 2.99 和 1,对于第二个示例,我能够得到 1.99、1 和 1。然而,在这两种情况下,结果都与预期的输出相差甚远。

我需要将邮政费用拆分为单独的行项目。结果可以等分或不等分,同时确保不同部分的总和等于输入的数字。

这里有一些其他的例子:

3.99 divided in 3 parts: 1.33, 1.33, 1.33
3.98 divided in 3 parts: 1.33, 1.33, 1.32
3.97 divided in 3 parts: 1.32, 1.32, 1.33
3.96 divided in 3 parts: 1.32, 1.32, 1.32
3.95 divided in 3 parts: 1.32, 1.32, 1.31

【问题讨论】:

  • 为什么不把3.99分成3部分改为1.33、1.33、1.33呢?
  • “但在这两种情况下,结果都与预期的输出相差甚远”——它有何不同?你尝试了什么?预期的结果是什么? What Have You tried?
  • @Naresh 为什么不1.32, 1.32, 1.33
  • 我认为这是一个非常好的问题,只是表达的不是很清楚。我认为纳雷什想要做的类似于在餐馆分摊账单。您希望平均分配价值,但不能收取低于 0.01 的价值——因此在某些情况下,一个人的收费比其他人多/少 0.01。
  • @Naresh 你的例子现在更清楚了,但是你的3.953.98 的例子是不一致的——一个你有x, x, x+0.02,另一个你有x, x+0.01, x+0.01。是否有理由对这些进行不同的处理,例如你更喜欢“偶数”?

标签: c#


【解决方案1】:

我有一个要求,其中 ex: 29 的数字被分成一个常量数组,余数必须附加在最后。

29= 9,9,9,3。为此,我的代码是。

       List<int> split(int num,int splitBy)
           {

               List<int> r = new List<int>();
               int v = Convert.ToInt32(num / splitBy);
               r.AddRange(Enumerable.Repeat(splitBy, v).ToArray());
               var remaining = num % splitBy;
               if (remaining != 0)
                   r.Add(remaining);
               return r;

           }

编码愉快!!!

【讨论】:

    【解决方案2】:

    如果有人打算使用扩展方法拆分四舍五入的数字,可以通过执行以下操作来完成。例如。将 25 分成 4 会得到类似 6,6,6,7 的结果。谢谢@乔恩 B

     public static IEnumerable<int> PartitionMeInto(this int value, int count)
        {
            if (count <= 0) throw new ArgumentException("count must be greater than zero.", "count");
            var result = new int[count];
    
            int runningTotal = 0;
            for (int i = 0; i < count; i++)
            {
                var remainder = value - runningTotal;
                var share = remainder > 0 ? remainder / (count - i) : 0;
                result[i] = share;
                runningTotal += share;
            }
    
            if (runningTotal < value) result[count - 1] += value - runningTotal;
    
            return result;
        }
    

    用法

            int value = 25;
    
            var result = value.PartitionMeInto(4);
    

    【讨论】:

      【解决方案3】:

      我使用您提供的值进行了测试。可能需要一些调整:

      static IEnumerable<decimal> SplitValue2(decimal value, int count)
      {
          if (count <= 0) throw new ArgumentException("count must be greater than zero.", "count");
          var result = new decimal[count];
      
          decimal runningTotal = 0M;
          for (int i = 0; i < count; i++)
          {
              var remainder = value - runningTotal;
              var share = remainder > 0M ? Math.Max(Math.Round(remainder / ((decimal)(count - i)), 2), .01M) : 0M;
              result[i] = share;
              runningTotal += share;
          }
      
          if (runningTotal < value) result[count - 1] += value - runningTotal;
      
          return result;
      }
      

      这假设您传入一个具有 2 位小数精度的值。如果你通过了 3.999,你将不会得到正确的结果。

      【讨论】:

      • 如果您愿意,可以使用(decimal.GetBits(value)[3] &gt;&gt; 16) % 256 获取输入小数中指定的小数位数。
      • 这不适用于count > 3;例如0.035 之间拆分得到.01 .01 .01 .01 -.01 而不是.01 .01 .01 0 0
      • @Rawling 不错。这有点极端,但我可以解决它。
      • 快点,因为如果重新打开,我会发布我自己的版本:p
      • 也许负面部分是一个糟糕的例子;这仍然保存了最后一个数字的所有“差异”,例如(1.03M, 5) 提供 .21 .21 .21 .21 .19 而不是 .21 .21 .21 .20 .20
      猜你喜欢
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-23
      • 2020-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多