Равномерно разделить на C # - PullRequest
4 голосов
/ 23 февраля 2009

В c # как равномерно разделить 100 на 7?

Таким образом, результат будет

  1. 16
  2. 14
  3. 14
  4. 14
  5. 14
  6. 14
  7. 14

Код ниже является неправильным, так как все 7 значений установлены на 15 (всего 105).

        double [] vals = new double[7];
        for (int i = 0; i < vals.Length; i++)
        {
            vals[i] = Math.Ceiling(100d / vals.Length);
        }

Есть ли простой способ сделать это в c #?

Спасибо

Ответы [ 6 ]

21 голосов
/ 23 февраля 2009

Чтобы получить мой предложенный результат 15, 15, 14, 14, 14, 14, 14:

// This doesn't try to cope with negative numbers :)
public static IEnumerable<int> DivideEvenly(int numerator, int denominator)
{
    int rem;
    int div = Math.DivRem(numerator, denominator, out rem);

    for (int i=0; i < denominator; i++)
    {
        yield return i < rem ? div+1 : div;
    }
}

Test:

foreach (int i in DivideEvenly(100, 7))
{
    Console.WriteLine(i);
}
6 голосов
/ 23 февраля 2009

Вот, пожалуйста:

Func<int, int, IEnumerable<int>> f = (a, b) => 
 Enumerable.Range(0,a/b).Select((n) => a / b + ((a % b) <= n ? 0 : 1))

Удачи, объясняя это в классе, хотя :)

5 голосов
/ 23 февраля 2009

Поскольку это, кажется, домашнее задание, вот подсказка, а не полный код.

Вы делаете Math.Ceiling, и он конвертирует 14.28 в 15.

1 голос
/ 23 февраля 2009

алгоритм такой

  1. Разделите 100 на 7, поместите результат в X
  2. Получите наибольшее четное число ниже X и поместите его в Y.
  3. Умножьте Y на 7 и поместите ответ в Z.
  4. Убери Z от 100.

Тогда ответом будет 6 лотов Y плюс любой результат шага 4.

Этот алгоритм может работать только для этого конкретного экземпляра.

Я уверен, что вы можете написать это в C #

0 голосов
/ 23 февраля 2009

Не знаю, почему вы работаете с двойными числами, но вам нужна семантика целочисленного деления.

    double input = 100;
    const int Buckets = 7;
    double[] vals = new double[Buckets];
    for (int i = 0; i < vals.Length; i++)
    {
        vals[i] = Math.Floor(input / Buckets);
    }
    double remainder = input % Buckets;
    // give all of the remainder to the first value
    vals[0] += remainder;

пример для целых с большей гибкостью,

    int input = 100;
    const int Buckets = 7;
    int [] vals = new int[Buckets];
    for (int i = 0; i < vals.Length; i++)
    {
        vals[i] = input / Buckets;
    }
    int remainder = input % Buckets;
    // give all of the remainder to the first value
    vals[0] += remainder;

    // If instead  you wanted to distribute the remainder evenly, 
    // priority to first
    for (int r = 0; r < remainder;r++)
    {
        vals[r % Buckets] += 1;
    }

Стоит отметить, что двойной пример не может быть численно стабильным , поскольку некоторые входные значения и размеры сегментов могут привести к утечке дробных значений.

0 голосов
/ 23 февраля 2009

Не уверен, что это именно то, что вам нужно, но я думаю, что если вы используете Math.ceiling, у вас всегда будет слишком большая сумма. Math.floor будет недооценивать и оставлять вас с разницей, которая может быть добавлена ​​к одной из ваших частей, как вы считаете нужным.

Например, с помощью этого метода вы можете получить 7 лотов из 14, что даст вам остаток 2. Затем вы можете либо сложить эти 2 в одну из своих частей, давая вам ответ, который вы предложили, либо разделить его равномерно и добавьте две части по 15 (как предложено в одном из комментариев)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...