【问题标题】:How to divide number into integer pieces that are each a multiple of n?如何将数字分成整数部分,每个部分都是 n 的倍数?
【发布时间】:2012-03-19 19:26:46
【问题描述】:

很难为此想出一个简洁的标题。我确信我想要完成的任务有一些术语,毫无疑问,一个通用的算法可以完成我所追求的 - 我只是还不知道它们。

我需要将一个数字分成 n 个部分,每个部分都是 50 的倍数。这个数字本身就是 50 的倍数。下面是一个示例: 将 5,000 除以 3,得到三个数字,每个数字都是 50 的倍数:

  • 1,650
  • 1,700
  • 1,650

我还希望分配数字以便它们来回翻转,这是一个带有更多数字的示例来说明这一点: 将 5,000 除以 7 得到 7 个数字,每个数字都是 50 的倍数:

  • 700
  • 750
  • 700
  • 750
  • 700
  • 700
  • 700

请注意,在上面的示例中,我并不担心额外的 50 不在系列中居中,也就是说我不需要这样的东西:

  • 700
  • 700
  • 750
  • 700
  • 750
  • 700
  • 700

希望我已经问得够清楚了,你明白我想要完成什么。

更新:这是我将要使用的功能。

var number = 5000;
var n = 7;
var multiple = 50;

var values = getIntDividedIntoMultiple(number, n, multiple)

function getIntDividedIntoMultiple(dividend, divisor, multiple)
{
    var values = [];
    while (dividend> 0 && divisor > 0)
    {
        var a = Math.round(dividend/ divisor / multiple) * multiple;
        dividend -= a;
        divisor--;
        values.push(a);
    }

    return values;
}

【问题讨论】:

  • 从您的示例中,您似乎希望每个较小的数字尽可能相等。那是对的吗?例如,一个简单的解决方案是对前 n-1 个数字中的每个数字取 50,其余的取其余数字,但我认为这不是您要寻找的...

标签: javascript algorithm math


【解决方案1】:
var number = 5000;
var n = 7;

var values = [];
while (number > 0 && n > 0) {
    var a = Math.floor(number / n / 50) * 50;
    number -= a;
    n--;
    values.push(a);
}  // 700 700 700 700 700 750 750

编辑

您可以交替使用Math.floorMath.ceil 以获得所需的结果:

while (number > 0 && n > 0) {
    if (a%2 == 0)
        a = Math.floor(number / n / 50) * 50;
    else
        a = Math.ceil(number / n / 50) * 50;
    number -= a;
    n--;
    values.push(a);
}  // 700 750 700 750 700 700 700

【讨论】:

  • 很好的例子,你将如何扩展它以向上和向下舍入切换,以便你有 700、750、700、750 等?
  • 是的,效果很好。我只是在调试器中单步调试代码并观察它是如何工作的,然后我就明白了。
  • 干净整洁,提供了一个 JS 示例,虽然不需要,但值得赞赏。
  • 我并不是说它是负面的,只是评论说考虑到您首先提供了一个 c 示例,因此感谢您为 JS 示例付出的额外努力。
【解决方案2】:

让 a 成为您的起始编号,k - 您想要划分的部分数。
假设 b = a/n。
现在你想把 b 分成 k 个接近的整数部分。

  • 取 k 个数字,每个等于 b/k(整数除法)。
  • 前 b%k 个数字加 1。
  • 将每个数字乘以 n。

示例: a = 5000,n = 50,k = 7。
b = 100
开始系列 {14, 14, 14, 14, 14, 14, 14}
将 1 加到前 2 个整数 {15, 15, 14, 14, 14, 14, 14}。
乘以 50 {750, 750, 700, 700, 700, 700, 700}。

【讨论】:

  • 起初它“哇!”用术语在我的头上,但在玩了一些代码之后,我明白了你现在在说什么;)
【解决方案3】:
// i - an integer multiple of k
// k - an integer
// n - a valid array length
// returns an array of length n containing integer multiples of k
// such that the elements sum to i and the array is sorted,
// contains the minimum number of unique elements necessary to
// satisfy the first condition, the elements chosen are the
// closest together that satisfy the first condition.
function f(i, k, n) {
  var minNumber = (((i / k) / n) | 0) * k;
  var maxNumber = minNumber + k;
  var numMax = (i - (minNumber * n)) / k;
  var nums = [];
  for (var i = 0; i < n - numMax; ++i) {
    nums[i] = minNumber;
  }
  for (var i = n - numMax; i < n; ++i) {
    nums[i] = maxNumber;
  }
  return nums;
}

所以你的第二个例子是

f(5000, 50, 7)

产生

[700,700,700,700,700,750,750]

【讨论】:

  • 很高兴看到不同的方法,这不是我想要的,因为 750 值是连续加载的。
【解决方案4】:

您的问题与将一个数字 X 划分为彼此相差 1 以内的 N 整数部分相同(找到结果后将所有内容乘以 50) .这样做很容易 - 将所有 N 数字设置为 Floor(X/N),然后将 1 添加到其中的 X mod N

【讨论】:

    【解决方案5】:

    我认为你的问题基本上是试图将一笔钱分成几捆几乎相等的一定面额的钞票。

    例如,将 10,000 美元分成 7 束几乎相等的 50 美元钞票。

    function getBundles(sum, denomination, count, shuffle)
    {
      var p = Math.floor(sum / denomination);
      var q = Math.floor(p / count);
      var r = p - q * count;
    
      console.log(r + " of " + ((q + 1) * denomination)
          + " and " + (count - r) + " of " + (q * denomination));
    
      var b = new Array(count);
      for (var i = 0; i < count; i++) {
        b[i] = (r > 0 && (!shuffle || Math.random() < .5 || count - i == r)
            ? (--r, q + 1) : q)
          * denomination;
      }
    
      return b;
    }
    
    // Divide 10,000 dollars into 7 near-equal bundles of 50-dollar bills
    var bundles = getBundles(10000, 50, 7, true);
    
    console.log("bundles: " + bundles);
    

    输出:

    4 of 1450 and 3 of 1400
    bundles: 1400,1450,1450,1400,1450,1400,1450
    

    如果最后一个参数shuffletrue,它会在捆绑包之间随机分配额外的数量。

    【讨论】:

      【解决方案6】:

      这是我的看法:

      public static void main(String[] args) {
          System.out.println(toList(divide(50, 5000, 3)));
          System.out.println(toList(divide(50, 5000, 7)));
          System.out.println(toList(divide(33, 6600, 7)));
      }
      
      private static ArrayList<Integer> toList(int[] args) {
          ArrayList<Integer> list = new ArrayList<Integer>(args.length);
          for (int i : args)
              list.add(i);
          return list;
      }
      
      public static int[] divide(int N, int multiplyOfN, int partsCount) {
          if (N <= 0 || multiplyOfN <= N || multiplyOfN % N != 0)
              throw new IllegalArgumentException("Invalid args");
      
          int factor = multiplyOfN / N;
          if (partsCount > factor)
              throw new IllegalArgumentException("Invalid args");
      
          int parts[] = new int[partsCount];
          int remainingAdjustments = factor % partsCount;
          int base = ((multiplyOfN / partsCount) / N) * N;
      
          for (int i = 0; i < partsCount; i ++) {
              parts[i] = (i % 2 == 1 && remainingAdjustments-- > 0) ? base + N : base;
          }
      
          return parts;
      }
      

      【讨论】:

      • 语言错误。至少它显示了你需要在 Java 中输入多少代码才能做一件简单的事情;)(无意冒犯)
      【解决方案7】:

      我的算法提供了跨部分的余数均匀分布:

      function splitValue(value, parts, multiplicity)
      {
          var result = [];
          var currentSum = 0;
          for (var i = 0; i < parts; i++)
          {
              result[i] = Math.round(value * (i + 1) / parts / multiplicity) * multiplicity - currentSum;
              currentSum += result[i];
          }
          return result;
      }
      

      对于 value = 5000,parts = 7,multiplicity = 50 它返回

      [ 700, 750, 700, 700, 700, 750, 700 ]
      

      【讨论】:

      • 多个未定义
      猜你喜欢
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-03
      相关资源
      最近更新 更多