javascript 如何将数字分成整数部分,每个部分都是n的倍数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9776555/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 07:48:25  来源:igfitidea点击:

How to divide number into integer pieces that are each a multiple of n?

javascriptalgorithmmath

提问by scubasteve

Had a hard time coming up with a concise title for this. I'm sure there are terms for what I want to accomplish and there is no doubt a common algorithm to accomplish what I'm after - I just don't know about them yet.

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

I need to break up a number into n pieces that are each a multiple of 50. The number is itself a multiple of 50. Here is an example: Divide 5,000 by 3 and end up with three numbers that are each multiples of 50:

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

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

I also would like to have the numbers distributed so that they flip back and forth, here is an example with more numbers to illustrate this: Divide 5,000 by 7 and end up with 7 numbers that are each multiples of 50:

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

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

Note that in the above example I'm not worried that the extra 50 is not centered in the series, that is I don't need to have something like this:

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

  • 700
  • 700
  • 750 <--- note the '50s' are centered
  • 700
  • 750 <--- note the '50s' are centered
  • 700
  • 700
  • 700
  • 700
  • 750 <--- 注意“50s”居中
  • 700
  • 750 <--- 注意“50s”居中
  • 700
  • 700

Hopefully I've asked this clearly enough that you understand what I want to accomplish.

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

Update: Here is the function I'll be using.

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

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;
}

回答by sch

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

Edit

编辑

You can alternate Math.floorand Math.ceilto obtain the desired result:

您可以交替使用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

回答by Mike Samuel

// 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;
}

So your second example would be

所以你的第二个例子是

f(5000, 50, 7)

which yields

这产生

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

回答by kilotaras

Let a be your starting number, k - number of parts you want to divide to.
Suppose, that b = a/n.
Now you want to divide b into k close integer parts.

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

  • Take k numbers, each equal to b/k (integer division).
  • Add 1 to first b%k numbers.
  • Multiply each number by n.
  • 取 k 个数字,每个数字都等于 b/k(整数除法)。
  • 将 1 添加到第一个 b%k 数字。
  • 将每个数字乘以 n。

Example: a = 5000, n = 50, k = 7.
b = 100
Starting series {14, 14, 14, 14, 14, 14, 14}
Add 1 to first 2 integers {15, 15, 14, 14, 14, 14, 14}.
Multiply by 50 {750, 750, 700, 700, 700, 700, 700}.

示例: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}。

回答by BlueRaja - Danny Pflughoeft

Your problem is the same as dividing a number Xinto Ninteger pieces that are all within 1 of each other (just multiply everything by 50 after you've found the result). Doing this is easy - set all Nnumbers to Floor(X/N), then add 1 to X mod Nof them.

你的问题是一样的分割数XN整数部件,它们都在彼此的1 (50只乘一切你已经找到了结果后)。这样做很容易 - 将所有N数字设置为Floor(X/N),然后X mod N在其中添加 1 。

回答by Manish

I see your problem as basically trying to divide a sum of money into near-equal bundles of bills of a certain denomination.

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

For example, dividing 10,000 dollars into 7 near-equal bundles of 50-dollar bills.

例如,将 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);

Output:

输出:

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

If the last argument shuffleis true, it distributes the extra amount randomly between the bundles.

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

回答by Gennadii Saltyshchak

My algorithm provides even distribution of remainder across parts:

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

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) * multiple - currentSum;
        currentSum += result[i];
    }
    return result;
}

For value = 5000, parts = 7, multiplicity = 50 it returns

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

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

回答by Victor Sorokin

Here's my take:

这是我的看法:

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;
}