Равномерно разделить на C#

В 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 ответов

Решение

Чтобы получить мой предложенный результат 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);
}

Ну вот:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам